10.1 knitr::kable()
関数
knitr パッケージの kable()
関数はとてもシンプルな表生成用の関数で, その設計もシンプルです. 行列やデータフレームのように厳密に矩形状のデータに対してのみ表を生成します. 表のセルを細かく整形したりセルを結合したりはできません. しかしこの関数は表の外見をカスタマイズする多くの引数を持っています.
kable(x, format, digits = getOption("digits"), row.names = NA,
col.names = NA, align, caption = NULL, label = NULL, format.args = list(),
escape = TRUE, ...)
10.1.1 サポートする表形式
データオブジェクト x
を単純な表で表すことだけが必要ならば, ほとんどの場合, knitr::kable(x)
で十分でしょう. format
引数は knitr のソース文書フォーマットに従って自動的に設定されます. 引数が取り得る値は列をパイプで区切った pipe
, Pandoc 式の単純な表である simple
, LaTeX の表 latex
, HTML の表 html
, reStructuredText (rst) 形式の rst
です. R Markdown 文書に対して kable()
はデフォルトで pipe
フォーマットを使用し, このような外見になります.
| | mpg| cyl| disp| hp|
|:-----------------|----:|---:|----:|---:|
|Mazda RX4 | 21.0| 6| 160| 110|
|Mazda RX4 Wag | 21.0| 6| 160| 110|
|Datsun 710 | 22.8| 4| 108| 93|
|Hornet 4 Drive | 21.4| 6| 258| 110|
|Hornet Sportabout | 18.7| 8| 360| 175| |Valiant | 18.1| 6| 225| 105|
単純な表, そして HTML, LaTeX, reStructuredText での表を生成できます.
mpg cyl disp hp
------------------ ----- ---- ----- ----
Mazda RX4 21.0 6 160 110
Mazda RX4 Wag 21.0 6 160 110
Datsun 710 22.8 4 108 93
Hornet 4 Drive 21.4 6 258 110
Hornet Sportabout 18.7 8 360 175 Valiant 18.1 6 225 105
<table>
<thead>
<tr>
<th style="text-align:left;"> </th>
<th style="text-align:right;"> mpg </th>
<th style="text-align:right;"> cyl </th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;"> Mazda RX4 </td>
<td style="text-align:right;"> 21 </td>
<td style="text-align:right;"> 6 </td>
</tr>
<tr>
<td style="text-align:left;"> Mazda RX4 Wag </td>
<td style="text-align:right;"> 21 </td>
<td style="text-align:right;"> 6 </td>
</tr>
</tbody>
</table>
\begin{tabular}{l|r|r|r|r}
\hline
& mpg & cyl & disp & hp\\
\hline
& 21.0 & 6 & 160 & 110\\
Mazda RX4 \hline
& 21.0 & 6 & 160 & 110\\
Mazda RX4 Wag \hline
& 22.8 & 4 & 108 & 93\\
Datsun 710 \hline
& 21.4 & 6 & 258 & 110\\
Hornet 4 Drive \hline
& 18.7 & 8 & 360 & 175\\
Hornet Sportabout \hline
& 18.1 & 6 & 225 & 105\\
Valiant \hline
\end{tabular}
================= ==== === ==== ===
\ mpg cyl disp hp
================= ==== === ==== ===
Mazda RX4 21.0 6 160 110
Mazda RX4 Wag 21.0 6 160 110
Datsun 710 22.8 4 108 93
Hornet 4 Drive 21.4 6 258 110
Hornet Sportabout 18.7 8 360 175
Valiant 18.1 6 225 105 ================= ==== === ==== ===
pipe
と simple
のフォーマットのみが移植可能だと覚えておいてください. つまり, これだけがどの出力文書フォーマットでも動作します. それ以外の表形式は特定のフォーマットに対してのみ, 例えば format = 'latex'
は LaTeX 出力に対してのみの動作です. 特定の表形式を使うことでより細かい操作ができますが, 代わりに移植性を犠牲にします.
特定の1つの表形式だけが必要で, それが文書のデフォルト形式でないなら, knitr.table.format
という R のグローバルオプションで一括設定できます. 例えばこのように.
このオプションには, 表形式を表す文字列か NULL
を返す関数を与えることもできます. NULL
の場合は knitr は適切な表形式を自動的に決定しようとします. 例えば出力フォーマットが LaTeX の場合のみ latex
を使用できます.
10.1.2 列名を変更する
データフレームの列の名前と読者に見せたいものとが一致するとは限りません. R のデータの列名でよくあるのは, 単語を区切るのにスペースを使わずドットやアンダースコアで代用します. これは表を読む上で不自然に感じるでしょう. col.names
引数を使うと列名を新しい名前のベクトルで置き換えることができます. 例えば iris
データの列名のドットをスペースに置換します.
Sepal Length | Sepal Width | Petal Length | Petal Width | Species |
---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | setosa |
4.9 | 3.0 | 1.4 | 0.2 | setosa |
4.7 | 3.2 | 1.3 | 0.2 | setosa |
4.6 | 3.1 | 1.5 | 0.2 | setosa |
5.0 | 3.6 | 1.4 | 0.2 | setosa |
5.4 | 3.9 | 1.7 | 0.4 | setosa |
col.names
引数には必ずしも gsub()
ような関数で列を与える必要はなく, 元のデータオブジェクトの列数と同じ長さであれば, 以下の例のように好きな文字列ベクトルを与えることができます.
10.1.3 列のアラインメントを指定する
表の各列のアラインメントを変更するには, 左揃え l
, 中央揃え c
, 右揃え r
のどれかと一致する1文字づつの文字ベクトルまたは, 1つの文字列で指定できます. よって kable(..., align = c('c', 'l'))
は kable(..., align = 'cl')
に省略できます. デフォルトでは, 数値列は右揃えで, それ以外は左揃えになります. これが使用例です.
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | setosa |
4.9 | 3.0 | 1.4 | 0.2 | setosa |
4.7 | 3.2 | 1.3 | 0.2 | setosa |
4.6 | 3.1 | 1.5 | 0.2 | setosa |
5.0 | 3.6 | 1.4 | 0.2 | setosa |
5.4 | 3.9 | 1.7 | 0.4 | setosa |
10.1.5 数値列を整形する
小数点以下の最大表示桁数を digits
引数で指定できます. 値は round()
関数に与えられるものと同じです. それ以外の整形用の引数は base R の format()
関数に与えられるものを format.args
に与えられます. まず round()
や format()
を使ったいくつかの簡単な例をお見せすれば, この後の kable()
引数がどう動作するか理解できることでしょう.
round(1.234567, 0)
## [1] 1
round(1.234567, digits = 1)
## [1] 1.2
round(1.234567, digits = 3)
## [1] 1.235
format(1000, scientific = TRUE)
## [1] "1e+03"
format(10000.123, big.mark = ",")
## [1] "10,000"
それでは表の数値を丸め整形します.
d <- cbind(X1 = runif(3), X2 = 10^c(3, 5, 7), X3 = rnorm(3, 0,
1000))
# 最大で4桁表示
knitr::kable(d, digits = 4)
X1 | X2 | X3 |
---|---|---|
0.0698 | 1e+03 | -571.9407 |
0.7653 | 1e+05 | -2161.6849 |
0.0049 | 1e+07 | -1705.9400 |
X1 | X2 | X3 |
---|---|---|
0.06975 | 1e+03 | -571.94 |
0.76528 | 1e+05 | -2161.68 |
0.00491 | 1e+07 | -1705.94 |
X1 | X2 | X3 |
---|---|---|
0.070 | 1000 | -571.941 |
0.765 | 100000 | -2161.685 |
0.005 | 10000000 | -1705.940 |
# 大きな数に対してカンマ区切りする
knitr::kable(d, digits = 3, format.args = list(big.mark = ",",
scientific = FALSE))
X1 | X2 | X3 |
---|---|---|
0.070 | 1,000 | -571.941 |
0.765 | 100,000 | -2,161.685 |
0.005 | 10,000,000 | -1,705.940 |
10.1.6 欠損値を表示する
デフォルトでは欠損値 (NA
) は表の上で NA
という文字で表示されます. これを R のグローバルオプション knitr.kable.NA
で他の値に置き換えたり何も表示させない, つまり NA
を空白にする, といったことができます. 例えば以下の2つ目の表では NA
を空白に置き換え, 3つ目の表で **
で表示しています.
X1 | X2 | X3 |
---|---|---|
NA | 1e+03 | -571.9 |
0.7653 | 1e+05 | NA |
0.0049 | NA | -1705.9 |
X1 | X2 | X3 |
---|---|---|
1e+03 | -571.9 | |
0.7653 | 1e+05 | |
0.0049 | -1705.9 |
X1 | X2 | X3 |
---|---|---|
** | 1e+03 | -571.9 |
0.7653 | 1e+05 | ** |
0.0049 | ** | -1705.9 |
10.1.7 特殊文字をエスケープする
あなたがもし HTML や LaTeX に詳しいなら, これらの言語にいくつかの特殊文字があることを知っているでしょう. 安全に出力するために, kable()
はデフォルトでは escape = TRUE
引数によって特殊文字をエスケープし, これは全ての文字がそのまま表示され, 特殊文字はその特別な意味を失います. 例えば >
は HTML の表に対しては >
に置き換えられ, LaTeX の表に対しては _
は \_
としてエスケープされます. あなたが専門家で, 特殊文字を適切に扱う方法を知っているなら, escape = FALSE
引数によってこれを無効化することもできます. 以下の2つ目の表では, 特殊文字である $
, \
, _
を含む LaTeX の数式表現を与えています.
Estimate | Std. Error | t value | Pr(>|t|) | |
---|---|---|---|---|
(Intercept) | -17.579 | 6.7584 | -2.601 | 0.0123 |
speed | 3.932 | 0.4155 | 9.464 | 0.0000 |
# 行と列の名前に数式表現を与える
rownames(d) <- c("$\\beta_0$", "$\\beta_1$")
colnames(d)[4] <- "$P(T > |t|)$"
knitr::kable(d, escape = FALSE)
Estimate | Std. Error | t value | \(P(T > |t|)\) | |
---|---|---|---|---|
\(\beta_0\) | -17.579 | 6.7584 | -2.601 | 0.0123 |
\(\beta_1\) | 3.932 | 0.4155 | 9.464 | 0.0000 |
escape = FALSE
なしでは特殊文字はエスケープされるか置き換えられます. 例えば $
は \$
に, _
は \_
に, \
は \textbackslash{}
にエスケープされます.
\begin{tabular}{l|r|r|r|r}
\hline
& Estimate & Std. Error & t value & \$P(T > |t|)\$\\
\hline
\$\textbackslash{}beta\_0\$ & -17.579 & 6.7584 & -2.601 & 0.0123\\
\hline
\$\textbackslash{}beta\_1\$ & 3.932 & 0.4155 & 9.464 & 0.0000\\
\hline
\end{tabular}
LaTeX で他によく知られた特殊文字として, #
, %
, &
, {
, }
があります. HTML のよく知られた特殊文字は &
, <
, >
そして "
です. escape = FALSE
で表を生成する際には, 正しい方法で特殊文字を使うよう注意深くなるべきです. とてもよくある失敗として, LaTeX で escape = FALSE
を使いつつ, %
や _
が特殊文字であると気づかずに表の列名やキャプションに含んでしまうというものがあります.
特殊文字のエスケープの方法を正しく知っている自信がないなら knitr には2つのヘルパー内部関数があります. 以下はその例です.
## [1] "100\\%" "\\# コメント" "列名"
## [1] "<アドレス>" "x = "文字列""
## [3] "a & b"
10.1.8 複数の表を横に並べる
データフレームや行列のリストを kable()
に与えて, 複数の表を並べて生成することができます. 例えば表10.2は以下のコードから生成された2つの表を含んでいます.
d1 <- head(cars, 3)
d2 <- head(mtcars[, 1:3], 5)
knitr::kable(
list(d1, d2),
caption = '横に並べられた2つの表',
booktabs = TRUE, valign = 't'
)
|
|
この機能は HTML と PDF 出力でのみ機能することに注意してください.
表を横に並べて個別の表をカスタマイズできるようにしたいと考えているなら, kables()
関数 (つまり, kable()
の複数形を意味しています) を使い, kable()
オブジェクトのリストを与えることもできます. 例えば, 表10.3の左の表の列名を変更し, かつ右の表の表示桁数をゼロに変更します.
# データオブジェクト d1, d2 は以前のコードチャンクのもの
knitr::kables(
list(
# 第1の kable() は列名を変更する
knitr::kable(
d1, col.names = c('速さ', '距離'), valign = 't'
),
# 第2の kable() は表示桁数を設定する
knitr::kable(d2, digits = 0, valign = 't')
),
caption = 'knitr::kables() によって作成された2つの表.'
)
|
|
10.1.9 for
ループから複数の表を作成する (*)
kable()
に関してよく混乱することの1つは, for
ループ内では動作しないということです. この問題は kable()
に限らず他のパッケージにも存在します. 原因は少々複雑です. 技術的な話に関心があるなら, “The Ghost Printer behind Top-level R Expressions.” というブログ記事で解説されています.
以下のコードチャンクは3つの表を生成する, とあなたは予想するかもしれませんが, そうはなりません.
```{r}
for (i in 1:3) {
knitr::kable(head(iris))
}
```
明示的に kable()
の結果をプリントし, チャンクオプション results = 'asis'
を適用しなければなりません. 例えばこのように.
```{r, results='asis'}
for (i in 1:3) {
print(knitr::kable(head(iris)))
}
```
一般に, for
ループ内で出力を生成するときは, 出力する要素をそれぞれ区別するためにそれぞれの直後に改行コード (\n
) または HTML のコメント行 (<!-- -->
) を加えることをおすすめします. これが例です.
```{r, results='asis'}
for (i in 1:3) {
print(knitr::kable(head(iris), caption = 'A caption.'))
cat('\n\n<!-- -->\n\n')
}
```
セパレータがないと Pandoc は個別の要素を検出するのに失敗します. 例えばグラフのすぐ後に表を続けて書いたとき, 表が認識されなくなります.
![](logo.png)
mpg cyl disp hp
------------------ ----- ---- ----- ----
Mazda RX4 21.0 6 160 110 Mazda RX4 Wag 21.0 6 160 110
しかし明示的に分離した場合はこうなります. 以下では画像の直後に空白行を挟んでいることに気をつけてください.
![](logo.png)
mpg cyl disp hp
------------------ ----- ---- ----- ----
Mazda RX4 21.0 6 160 110 Mazda RX4 Wag 21.0 6 160 110
あるいはこのように.
![](logo.png)
<!-- -->
mpg cyl disp hp
------------------ ----- ---- ----- ----
Mazda RX4 21.0 6 160 110 Mazda RX4 Wag 21.0 6 160 110
10.1.10 LaTeX の表をカスタマイズする (*)
必要なのが LaTeX の出力のみなら, さらにいくつか kable()
のオプションがあります. これらは HTML 等, 他の種類のフォーマットでは無視されることに注意してください. 表のフォーマットオプションをグローバルに設定 (10.1.1節参照) していない限り, この節の例では kable()
の format
引数を明示的に使わなければなりません.
表のキャプションを設定 (10.1.4節参照) している場合, kable()
は表を table
環境で囲みます. つまりこうなります.
\begin{table}
% the table body (usually the tabular environment)
\end{table}
この環境は table.envir
引数で次のように変更できます.
\begin{figure}
\begin{tabular}{r|r}
\hline
& dist\\
speed \hline
& 2\\
4 \hline
& 10\\
4 \hline
\end{tabular}
\end{figure}
表のフロート位置は position
引数によって制御されます. 例えば position = "!b"
によって表のフロートをページ下部に置くことを強制できます.
\begin{table}[!b]
\begin{tabular}{r|r}
\hline
& dist\\
speed \hline
& 2\\
4 \hline
& 10\\
4 \hline
\end{tabular}
\end{table}
表にキャプションがある場合, caption.short
引数でこの例のようにキャプションの短縮形を与えることもできます.
キャプションの短縮形は LaTeX 上では \caption[]{}
コマンドのブラケット ([]
) 内に与えられ, ほとんどの場合は出力された PDF の表一覧で使用されます. 短縮形がない場合は, キャプション全文が表示されます.
出版物レベルのクオリティで作表するための LaTeX パッケージ booktabs に詳しいなら, この例のように booktabs = TRUE
を設定できます.
\begin{tabular}{rrrrl}
\toprule
& Sepal.Width & Petal.Length & Petal.Width & Species\\
Sepal.Length \midrule
& 3.5 & 1.4 & 0.2 & setosa\\
5.1 & 3.0 & 1.4 & 0.2 & setosa\\
4.9 & 3.2 & 1.3 & 0.2 & setosa\\
4.7 & 3.1 & 1.5 & 0.2 & setosa\\
4.6 & 3.6 & 1.4 & 0.2 & setosa\\
5.0 \addlinespace
& 3.9 & 1.7 & 0.4 & setosa\\
5.4 & 3.4 & 1.4 & 0.3 & setosa\\
4.6 & 3.4 & 1.5 & 0.2 & setosa\\
5.0 & 2.9 & 1.4 & 0.2 & setosa\\
4.4 & 3.1 & 1.5 & 0.1 & setosa\\
4.9 \bottomrule
\end{tabular}
R Markdown で booktabs のような LaTeX パッケージが追加で必要なら, YAML で宣言しなければならないことを忘れないでください (やり方は6.4節参照).
引数 booktabs
が TRUE
か FALSE
(デフォルト) であるかに依存して表の外見は変わります.
booktabs = FALSE
の場合
- 表の列が垂直線で区切られます.
vline
引数を使って垂直線を削除することができます. 例えばknitr::kable(iris, vline = "")
と言うふうにします. デフォルトはvline = "|"
です.このオプションをグローバルに設定することもでき, 表ごとに指定する必要はありません. 例えばoptions(knitr.table.vline = "")
とします. - 水平線を
toprule
,midrule
,linesep
,bottomrule
引数で定義できます. これらのデフォルト値は\hline
です.
booktabs = TRUE
の場合
表に垂線はありませんが,
vline
引数で追加することができます.テーブルのヘッダと末尾にのみ水平線が描かれます. デフォルトの引数の値は
toprule = "\\toprule"
,midrule = "\\midrule"
,bottomrule = "\\bottomrule"
です. デフォルトでは1行分の空きが5行ごとに挿入されます. これはlinesep
引数で制御でき, このデフォルトはc("", "", "", "", "\\addlinespace")
となっています. 3行ごとに空白を与えたいなら, このようにできます.\begin{tabular}{rrrrl} \toprule & Sepal.Width & Petal.Length & Petal.Width & Species\\ Sepal.Length \midrule & 3.5 & 1.4 & 0.2 & setosa\\ 5.1 & 3.0 & 1.4 & 0.2 & setosa\\ 4.9 & 3.2 & 1.3 & 0.2 & setosa\\ 4.7 \addlinespace & 3.1 & 1.5 & 0.2 & setosa\\ 4.6 & 3.6 & 1.4 & 0.2 & setosa\\ 5.0 & 3.9 & 1.7 & 0.4 & setosa\\ 5.4 \addlinespace & 3.4 & 1.4 & 0.3 & setosa\\ 4.6 & 3.4 & 1.5 & 0.2 & setosa\\ 5.0 & 2.9 & 1.4 & 0.2 & setosa\\ 4.4 \addlinespace & 3.1 & 1.5 & 0.1 & setosa\\ 4.9 \bottomrule \end{tabular}
行空けを完全に削除したいなら,
linesep = ''
とこともできます.
表がページよりも長くなってしまうもともあるでしょう. そのような場合は longtable = TRUE
を使用できます. このオプションは LaTeX パッケージ longtable を使い表を複数ページに分割します.
table 環境に含まれた場合, つまり表にキャプションを設定した場合は表はデフォルトで中央揃えになります. 表を中央揃えにしたくないなら, centering = FALSE
引数を使用してください.
10.1.11 HTML の表をカスタマイズする (*)
knitr::kable(format = "html")
で生成した表をカスタマイズしたいなら, 前節で紹介した共通の引数の他に, 1つだけ table.attr
という特別な引数があります. この引数で任意の属性を <table>
タグに追加することができます. 例えばこのように.
<table class="striped">
<thead>
<tr>
<th style="text-align:left;"> </th>
<th style="text-align:right;"> mpg </th>
<th style="text-align:right;"> cyl </th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;"> Mazda RX4 </td>
<td style="text-align:right;"> 21 </td>
<td style="text-align:right;"> 6 </td>
</tr>
<tr>
<td style="text-align:left;"> Mazda RX4 Wag </td>
<td style="text-align:right;"> 21 </td>
<td style="text-align:right;"> 6 </td>
</tr>
</tbody>
</table>
表に striped
クラスを追加しています. しかしクラス名だけでは表の外見を変更するのに不十分です. クラスに対して CSS ルールを定義しなければなりません. 例えば偶数列と奇数列とで色の異なるストライプ背景の表を作るには, 明灰色の背景を偶数または奇数列に追加できます.
.striped tr:nth-child(even) { background: #eee; }
上記の CSS ルールの意味は, striped
クラスを持つ要素の子要素ですべての行(つまり <tr>
タグ )のうち行番号が偶数属性の (:nth-child(even)
) 要素は, 背景色が #eee
になるということです.
少しの CSS の記述だけでプレーンの HTML の表の見栄えをよくできます. 図10.1は, 以下の CSS ルールを適用した HTML 表のスクリーンショットです
table {margin: auto;
border-top: 1px solid #666;
border-bottom: 1px solid #666;
}border-bottom: 1px solid #ddd; }
table thead th { , td { padding: 5px; }
th, tfoot, tr:nth-child(even) { background: #eee; } thead