Edited at

R MarkdownでコードからMarkdown生成するTips

More than 1 year has passed since last update.


R Markdownで資料作成する

何かしらのデータの中身をざっくり調べて、資料化したいとき、R Markdownを使うと便利です。

その時に使えるちょっとしたTipsをメモしておきます。


全体設定


テーマ変更

R Studioを使ってR Markdownを新規作成します。

最初に生成されるテンプレートの一番上にこういう記述があります。

---

title: "Untitled"
output: html_document
---

このoutputの部分に設定を追加することで出力形式を変えたり、出力時のテーマを変えたりできます。

---

title: "データ確認R Markdown"
output:
html_document:
toc: true
toc_depth: 2
toc_float: true
number_section: true
theme: cerulean
--

tocで目次を出したり、number_sectionで章番号をつけたり、themeで全体のテンプレートを変えたりできます。

themeはBootswatchのものが内部で使われているようで、


Valid themes include "default", "cerulean", "journal", "flatly", "readable", "spacelab", "united", "cosmo", "lumen", "paper", "sandstone", "simplex", and "yeti".


が指定できます。

theme: ceruleanを指定したところ、こんな感じの目次が生成されて、色も青っぽくなりました。


チャンク設定

チャンクのデフォルト設定を変更することができます。

例えば、ソースコードも含めて資料化したい場合はecho=Tを、ソースコードは基本出さないという場合はecho=Fを指定しておくと便利です。

knitr::opts_chunk$set(echo = F)


Markdown生成


マークダウン内にRの結果を埋め込む

R Markdownのシンプルな書き方はチャンクの中にRのコードを書くと、結果が出るというもの。

※Qiita上で```を書くとコードとして扱われるため、最後の一つをシングルクオートに変えていますので、コピペの際は注意

```{r}

head(data, 1)
``'



この場合、マークダウンの文章とは別に結果が表示されます。

マークダウンの文章中に結果を埋め込みたい場合は 'r'という1行の書き方にすると可能です。

例えば、こういう書き方をすると、

- 入力ファイル:sample.csv

- データ数: `r nrow(data)` x `r ncol(data)`

```{r comment=NA}
cat("- データ数: `r nrow(data)` x `r ncol(data)`")
``'



'r nrow(data)'というように書いたところはマークダウンに展開されて結果が出力され、下側のcat()で出力しているところはあくまでRの処理結果として出力された文字列が生成されます。

また、表を出力したい場合はknitr::kable()を使うとマークダウンで出力されます


テキストをマークダウンとして出力

プログラムでマークダウンを生成して出力したい場合、knit_expand()を使うと可能です。

'r paste(knit_expand(text = out), collapse = '\n')'のような感じでtext = "文字列"を指定し、pasteで出力します。

```{r}

out <- c("- hoge","- fuga")
``'

`r paste(knit_expand(text = out), collapse = '\n')`



さらに、変数を埋め込むことも可能です。{{ }}で名前をつけておいて、knit_expand()の第2引数以降に指定すると埋め込むことが可能です。

```{r}

moji <- "文字"
out <- c("- 箇条書き1",
"- 箇条書き2",
paste0("- ", moji), # 単に変数を展開さすこともできる
paste0("- [{{hoge}}]({{fuga}})")) # 後で埋め込む変数名を定義
``'

`r paste(knit_expand(text = out, hoge="Googleリンク", fuga="http://www.google.co.jp"), collapse = '\n')`

[タイトル](リンク先)がリンクの書式なので、以下のように展開されます。


応用

これらを応用して、データフレームを列ごとに調査してMarkdownにまとめる、ということをやってみます。

少しややこしいですが、列ごとに型を調べ、数値型なら四分位を、factor型なら集計結果を算出して、章立てを構成するということをやってみます。

サンプルデータも貼り付けてるので長いです。

※例のごとくチャンクの終わりの```は最後の一つを'にしています

# さくっとデータ確認

R Markdownでデータ確認内容をまとめる際のTips集です。

- ここはふつうのMarkdown
- 箇条書き
- hoge

## データ読み込みと型変換
```{r}
data <- data.frame(
"日付YMD"=c("2018/02/01","2018/02/02","2018/02/09","2018/02/10","2018/02/11","2018/02/18","2018/02/20","2018/02/21","2018/02/22","2018/02/24","2018/02/25","2018/02/26","2018/03/07","2018/03/08","2018/03/09","2018/03/10","2018/03/11","2018/03/12","2018/03/14","2018/03/15","2018/03/16","2018/03/17","2018/03/18","2018/03/19","2018/03/20","2018/03/24","2018/03/25","2018/03/27","2018/03/28","2018/03/29","2018/03/30","2018/03/31","2018/04/01","2018/04/02"),
"日付YMDHMS"=c("2018/01/15 12:12:00","2018/01/16 12:12:00","2018/01/23 12:12:00","2018/01/24 12:12:00","2018/01/25 12:12:00","2018/02/01 12:12:00","2018/02/03 12:12:00","2018/02/04 12:12:00","2018/02/05 12:12:00","2018/02/07 12:12:00","2018/02/08 12:12:00","2018/02/09 12:12:00","2018/02/18 12:12:00","2018/02/19 12:12:00","2018/02/20 12:12:00","2018/02/21 12:12:00","2018/02/22 12:12:00","2018/02/23 12:12:00","2018/02/25 12:12:00","2018/02/26 12:12:00","2018/02/27 12:12:00","2018/02/28 12:12:00","2018/03/01 12:12:00","2018/03/02 12:12:00","2018/03/03 12:12:00","2018/03/07 12:12:00","2018/03/08 12:12:00","2018/03/10 12:12:00","2018/03/11 12:12:00","2018/03/12 12:12:00","2018/03/13 12:12:00","2018/03/14 12:12:00","2018/03/15 12:12:00","2018/03/16 12:12:00"),
"数字"=c(1.005418711,-0.678388247,1.304724134,-0.505765604,0.922991683,0.840653049,0.457446012,-0.6683536,0.275588407,-0.72649637,-0.752952974,-0.279135363,-0.279816282,-1.063173358,0.497759081,-0.15509664,0.961377702,0.621827645,2.149482626,0.608389865,1.685698082,1.072128114,1.725331574,0.973425877,-1.32760823,2.391989691,-0.937037714,2.137561967,1.852441953,-0.411203065,1.282303024,1.275440471,-1.067788693,-1.265772412),
"カテゴリ"=c("A","A","A","A","A","A","A","A","A","A","B","B","C","C","C","C","C","C","C","C","C","C","C","C","C","D","E","E","E","E","E","E","E","E"),
"文字"=c("学習デ","という","だけデ","学習デ","ていき","タを使","クにな","を決め","て何日","ぐらい","う応用","まうと","ータ貯","いう応","。1年","習デー","まらな","かを学","を予測","それだ","という","ないと","どの","を予測","のデー","使って","どの","応用し","を学習","めてい","まうと","決めて","先を予","タを使"),
"時系列"=c(-0.239960181,-0.717208315,-0.581798577,-0.499899009,-0.497580065,-0.302588978,-0.592474074,-0.999182116,-0.528313479,-0.195930277,-0.589054216,-0.530858236,-0.286202981,-0.38340551,-0.23803448,0.141907181,0.28102854,0.213004386,-0.204558427,-0.437323025,-0.769930558,-1.044455817,-0.869149268,-1.26702972,-1.042433517,-0.63207571,-0.983444224,-0.971029176,-1.054820843,-1.031256202,-1.440652867,-1.246845769,-1.260898147,-1.555620586)
)

``'

```{r ,echo=T, comment=NA}
data$`日付YMD` <- as.Date(data$`日付YMD`)
data$`日付YMDHMS` <- as.POSIXlt(data$`日付YMDHMS`)
data$`時系列` <- ts(data$`時系列`)
``'

## 全体の俯瞰

- 入力ファイル:hoge.csv
- データ数: `r nrow(data)` x `r ncol(data)`

### 表の生成
- 横
```{r}
kable(head(data, 1))
``'

- 縦
```{r}
# magrittr
head(data, 1) %>% t %>% kable
``'

```{r}
### 関数定義いろいろ ###

# tableにパーセント表記を追加
table.per <- function(d){
count <- table(d)
percent <- round(prop.table(count) * 100,2)
ret <- data.frame("name"=names(count),
"count"=as.numeric(count),
"percent"=as.numeric(percent))
ret
}

# numeric型の場合の処理
md_numeric <- function(d){
kable(summary(d) %>% c %>% t)
}

# ts型の場合の処理
md_ts <- function(d){
c("- ", paste(c("Start","End","Frequency"),tsp(d),sep=": "))
}

# Date型の場合の処理
md_date <- function(d){
d.sorted <- sort(d)
paste0("- From - To:: ", d.sorted[1], " ~ ", rev(d.sorted)[1])
}

# factor型の場合の処理
md_factor <- function(d){
uniq <- unique(d)
ret <- paste0("- ユニーク要素数:: ", length(uniq), '\n')
if(length(uniq) < 10){
tbl <- table.per(d)
ret <- c(ret, tbl %>% kable, '\n')
}
ret
}

``'

```{r}
out <- "## 一列ずつ要素の確認"
out <- c(out, "列ごとに処理を行い、結果を出力します\n")

for(col in names(data)){
d <- data[,col]
cls <- class(d)[1]

out <- c(out, paste0("### ", col, "(", cls, "型)", '\n'))

# 型により処理分岐
if("numeric" %in% cls){
md_func <- md_numeric
}else if("ts" %in% cls){
md_func <- md_ts
}else if(0 < sum(c("Date","POSIXlt") %in% cls)){
md_func <- md_date
}else{
md_func <- md_factor
}
out <- c(out, md_func(d), '\n')
}

``'

`r paste(knit_expand(text = out), collapse = '\n')`

結果

これはもう少しちゃんと関数化して、データフレームを放り込めば、きれいに出力されるようにすれば使いやすくなるかも。

あと、グラフを挿入するのはまだわからないので、まだまだ改善の余地はありそうです。