gt入門
はじめに
- 以下の内容は現在執筆中の内容の一部となります。
- 本記事で使用するデータは以下からダウンロードしてください。
ファイル名 | ダウンロード |
---|---|
countries_desc1.csv |
Download |
countries_desc2.csv |
Download |
countries_desc3.csv |
Download |
記述統計や推定結果を示す場合は図表が用いられることが多い。図に関しては{ggplot2}が最もポピュラーなパッケージである(Base Rもまた根強い人気を誇る)。一方、表の場合、現時点において2つの選択肢がある。一つはこれまで長らく使われてきた{knitr}パッケージのkable()
と{kabelExtra}パッケージの組み合わせ、もう一つが近年注目を集めている{gt}パッケージだ。
{gt}はGrammar of Tablesの略であり、Grammar of Graphicsの具現化した{ggplot2}の影響を受けたものである。つまり、一つの表を独立した要素に分解し、それぞれのレイヤーを重ねていくイメージだ。{ggplot2}の考え方(\(\neq\)使い方)に慣れている読者なら{gt}にもすぐ慣れるだろう。ただし、{gt}は開発途上であり、PDF出力との相性が現在 (2023年08月29日; {gt} 0.9.0)、優れているとはいい難い。表をPDF形式に出力したいのであれば{knitr}のkable()
+ {kableExtra}を推奨する。また、{gt}単体での機能はkable()
+ {kableExtra}より貧弱ではあったものの、現在は{gtExtras}の登場により、ほぼ同じことが行えるようになった。
ここではRStudio社が開発をサポートしている{gt}パッケージについて簡単に解説する1。また、どのパッケージもHTML出力とLaTeX出力両方に対応しているが、ここではHTML出力のみ紹介する。ただし、LaTeX出力に関しては引数の追加などで簡単にできるため、詳細は各パッケージの公式ページやヴィネット等を参考されたい。
それではまず、実習に使用するパッケージとデータを読み込でおこう。
# A tibble: 7 × 6
Variable Mean SD Min Max Obs
<chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Population 41.7 151. 0.000801 1447. 186
2 Area 69.6 187. 0 1638. 186
3 GDP_per_capita 1.62 2.57 0.00577 18.3 185
4 PPP_per_capita 2.08 2.10 0.0733 11.3 178
5 HDI_2018 0.713 0.153 0.377 0.954 180
6 Polity_Score 4.26 6.10 -10 10 158
7 FH_Total 57.7 29.9 0 100 185
# A tibble: 35 × 7
Continent Variable Mean SD Min Max Obs
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Africa Population 24.6 35.9 0.0983 206. 54
2 Africa Area 54.4 59.2 0.046 238. 54
3 Africa GDP_per_capita 0.251 0.313 0.00577 1.73 54
4 Africa PPP_per_capita 0.567 0.602 0.0733 2.78 52
5 Africa HDI_2018 0.553 0.109 0.377 0.801 53
6 Africa Polity_Score 2.48 5.00 -9 10 48
7 Africa FH_Total 41.6 25.1 2 92 54
8 America Population 28.7 66.3 0.0532 334. 36
9 America Area 108. 246. 0.026 916. 36
10 America GDP_per_capita 1.25 1.27 0.0745 6.44 36
# ℹ 25 more rows
# A tibble: 5 × 8
Continent Population Area GDP PPP HDI Polity FH
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Africa 24.6 54.4 0.251 0.567 0.553 2.48 41.6
2 America 28.7 108. 1.25 1.81 0.742 6.93 71.9
3 Asia 107. 70.2 1.32 2.27 0.723 0.342 38.9
4 Europe 17.1 46.5 3.56 3.78 0.861 7.93 79.4
5 Oceania 10.0 210. 2.66 2.76 0.782 7.25 79
{gt}の使い方
表の出力
{gt}では、表がタイトル、列ラベル、ホディ―などの要素で構成されている考え( 図 1 )、それぞれの要素を追加したり、修正する形で表を作成する。
まず、これまで使ってきたdf1
を使ってHTML形式の表を出力してみよう。使用する関数はgt()
であり、data.frameまたはtibbleオブジェクト名が第1引数である。
Variable | Mean | SD | Min | Max | Obs |
---|---|---|---|---|---|
Population | 41.7377735 | 151.2702976 | 0.000801000 | 1447.47009 | 186 |
Area | 69.6069247 | 187.2412489 | 0.000000000 | 1637.68700 | 186 |
GDP_per_capita | 1.6158103 | 2.5710359 | 0.005770007 | 18.31772 | 185 |
PPP_per_capita | 2.0833383 | 2.0992134 | 0.073314173 | 11.34231 | 178 |
HDI_2018 | 0.7134833 | 0.1528503 | 0.377000000 | 0.95400 | 180 |
Polity_Score | 4.2594937 | 6.1022919 | -10.000000000 | 10.00000 | 158 |
FH_Total | 57.7135135 | 29.8656244 | 0.000000000 | 100.00000 | 185 |
列の操作
これだけでも十分に綺麗な表が出来上がった。それではこちらの表を少しずつ修正してみよう。まず、Mean列からMax列だが、これを小数点3桁で丸めてみよう。これらの数字は 図 1 のTable Bodyに該当する。このTable Bodyのフォーマットに関わる調整はfmt_*()
関数を使用する。Mean
列からMax
列までの数値に関する調整はfmt_number()
関数を使用する。gt()
で作成された表オブジェクトをそのままfmt_number()
に渡し、columns
引数で何列に当該内容を適用するかを指定する。たとえば、Mean列からMax列までは2〜5列目に相当するのでcolumns = 2:5
、またはcolumns = c(2, 3, 4, 5)
で良い。続いて、小数点の桁数を指定するdecimals
に3を指定してみよう。
Variable | Mean | SD | Min | Max | Obs |
---|---|---|---|---|---|
Population | 41.738 | 151.270 | 0.001 | 1,447.470 | 186 |
Area | 69.607 | 187.241 | 0.000 | 1,637.687 | 186 |
GDP_per_capita | 1.616 | 2.571 | 0.006 | 18.318 | 185 |
PPP_per_capita | 2.083 | 2.099 | 0.073 | 11.342 | 178 |
HDI_2018 | 0.713 | 0.153 | 0.377 | 0.954 | 180 |
Polity_Score | 4.259 | 6.102 | −10.000 | 10.000 | 158 |
FH_Total | 57.714 | 29.866 | 0.000 | 100.000 | 185 |
columns
は列の番号じゃなく、列名そのままでも指定できる。
Variable | Mean | SD | Min | Max | Obs |
---|---|---|---|---|---|
Population | 41.738 | 151.270 | 0.001 | 1,447.470 | 186 |
Area | 69.607 | 187.241 | 0.000 | 1,637.687 | 186 |
GDP_per_capita | 1.616 | 2.571 | 0.006 | 18.318 | 185 |
PPP_per_capita | 2.083 | 2.099 | 0.073 | 11.342 | 178 |
HDI_2018 | 0.713 | 0.153 | 0.377 | 0.954 | 180 |
Polity_Score | 4.259 | 6.102 | −10.000 | 10.000 | 158 |
FH_Total | 57.714 | 29.866 | 0.000 | 100.000 | 185 |
列名の変更はcols_lable()
レイヤーで行う。()
内には"元の列名" = "新しい列名"
のように記述する。kbl()
は全ての列に対して列名を指定しないといけなかったが(つまり、変更したくない列も一応、指定が必要)、{gt}だと変更したい列のみ指定しても良いといったメリットがある。
df1 |>
gt() |>
fmt_number(columns = 2:5, decimals = 3) |>
cols_label("Variable" = "変数", "Mean" = "平均値", "SD" = "標準偏差",
"Min" = "最小値", "Max" = "最大値", "Obs" = "有効ケース数")
変数 | 平均値 | 標準偏差 | 最小値 | 最大値 | 有効ケース数 |
---|---|---|---|---|---|
Population | 41.738 | 151.270 | 0.001 | 1,447.470 | 186 |
Area | 69.607 | 187.241 | 0.000 | 1,637.687 | 186 |
GDP_per_capita | 1.616 | 2.571 | 0.006 | 18.318 | 185 |
PPP_per_capita | 2.083 | 2.099 | 0.073 | 11.342 | 178 |
HDI_2018 | 0.713 | 0.153 | 0.377 | 0.954 | 180 |
Polity_Score | 4.259 | 6.102 | −10.000 | 10.000 | 158 |
FH_Total | 57.714 | 29.866 | 0.000 | 100.000 | 185 |
もう一つ見たいこところは、各セル内のテキストの揃えだ。たとえば、文字型列のVariableは左揃え、数値型列であるその他の列は右揃えになっている。これはこのままで問題ない。しかし、どうしても特定の列を中央揃えしたい時もあるだろう。その場合、cols_align()
レイヤーで修正することができる。たとえば、Variable列の値を中央揃えに変えてみよう。引数はalign
で"left"
、"center"
、"right"
のいずれかを、columns
には適用したい列の番号、または列名を指定する。
df1 |>
gt() |>
fmt_number(columns = 2:5, decimals = 3) |>
cols_align(align = "center", columns = 1) # columns = Variable でもOK
Variable | Mean | SD | Min | Max | Obs |
---|---|---|---|---|---|
Population | 41.738 | 151.270 | 0.001 | 1,447.470 | 186 |
Area | 69.607 | 187.241 | 0.000 | 1,637.687 | 186 |
GDP_per_capita | 1.616 | 2.571 | 0.006 | 18.318 | 185 |
PPP_per_capita | 2.083 | 2.099 | 0.073 | 11.342 | 178 |
HDI_2018 | 0.713 | 0.153 | 0.377 | 0.954 | 180 |
Polity_Score | 4.259 | 6.102 | −10.000 | 10.000 | 158 |
FH_Total | 57.714 | 29.866 | 0.000 | 100.000 | 185 |
また、各列のラベル(図 1 のcolumn labels)の位置も表のボディー(図 1 のtable body)に連動する。もし、列ラベルのみ中央揃えにしたい場合はtab_style()
レイヤーを使用する。
df1 |>
gt() |>
fmt_number(columns = 2:5, decimals = 3) |>
tab_style(style = cell_text(align = "center"), # どうする?: 中央揃え
locations = cells_column_labels()) # どこを?: 列レベルだけ
Variable | Mean | SD | Min | Max | Obs |
---|---|---|---|---|---|
Population | 41.738 | 151.270 | 0.001 | 1,447.470 | 186 |
Area | 69.607 | 187.241 | 0.000 | 1,637.687 | 186 |
GDP_per_capita | 1.616 | 2.571 | 0.006 | 18.318 | 185 |
PPP_per_capita | 2.083 | 2.099 | 0.073 | 11.342 | 178 |
HDI_2018 | 0.713 | 0.153 | 0.377 | 0.954 | 180 |
Polity_Score | 4.259 | 6.102 | −10.000 | 10.000 | 158 |
FH_Total | 57.714 | 29.866 | 0.000 | 100.000 | 185 |
また、HTMLのCSSによって異なるが、{gt}で作成された表の幅がページの幅に強制的に調整される場合がある。本書はQuartoで執筆されているが、まさにそのケースである。この場合は、as_raw_html()
を使えば良い。一つ注意すべき点はas_raw_html()
は必ず最後のレイヤーにする必要がある。as_raw_html()
の後ろにレイヤーが足される場合はエラーが発生する。
Variable | Mean | SD | Min | Max | Obs |
---|---|---|---|---|---|
このas_raw_html()
は必要に応じて入れる。R Markdown/Quartoを使わない場合はそもそも不要だ(RStudioのViewerペインでは問題なく表示される)。もし、R Markdown/Quartoで{gt}を使用し、表の幅が気に入らない場合のみ使うことにしよう。
タイトル・フットノート
表のタイトルおよびサブタイトルはtab_header()
関数のtitle
とsubtitle
引数で指定できる。また、表の下段に位置するフットノート(footnote)とソースノート(source note)は別の関数に対応し、それぞれtab_footnote()
とtab_source_note()
を使う。使用する引数はそれぞれfootnote
とsource_note
であるが、第1引数であるため、省略可能だ。
df1 |>
gt() |>
fmt_number(columns = 2:5, decimals = 3) |>
tab_header(title = "タイトル", subtitle = "サブタイトル") |>
tab_footnote(footnote = "注: ここにはフットノートが入る") |>
tab_source_note(source_note = "出典: 『私たちのR』") |>
as_raw_html()
タイトル | |||||
サブタイトル | |||||
Variable | Mean | SD | Min | Max | Obs |
---|---|---|---|---|---|
出典: 『私たちのR』 | |||||
注: ここにはフットノートが入る |
ちなみに、tab_footnote()
やtab_source_note()
は複数回使用することで複数行にすることができる。
df1 |>
gt() |>
fmt_number(columns = 2:5, decimals = 3) |>
tab_header(title = "タイトル", subtitle = "サブタイトル") |>
tab_footnote(footnote = "注1: ここにはフットノート1が入る") |>
tab_footnote(footnote = "注2: ここにはフットノート2が入る") |>
tab_source_note(source_note = "出典: 『私たちのR』") |>
as_raw_html()
タイトル | |||||
サブタイトル | |||||
Variable | Mean | SD | Min | Max | Obs |
---|---|---|---|---|---|
出典: 『私たちのR』 | |||||
注1: ここにはフットノート1が入る | |||||
注2: ここにはフットノート2が入る |
また、タイトルやフットノートに限定された機能ではないが、テキストはMarkdownやHTML文法で書くこともできる。たとえば、上記のコードの『私たちのR』にリンクを貼る場合、Markdown文法だと"『[私たちのR](https://www.jaysong.net/RBook/)』"
となるが、このままではうまくいかない。
df1 |>
gt() |>
fmt_number(columns = 2:5, decimals = 3) |>
tab_header(title = "タイトル", subtitle = "サブタイトル") |>
tab_footnote(footnote = "注1: ここにはフットノート1が入る") |>
tab_footnote(footnote = "注2: ここにはフットノート2が入る") |>
tab_source_note(source_note = "出典: 『[私たちのR](https://www.jaysong.net/RBook/)』") |>
as_raw_html()
タイトル | |||||
サブタイトル | |||||
Variable | Mean | SD | Min | Max | Obs |
---|---|---|---|---|---|
出典: 『[私たちのR](https://www.jaysong.net/RBook/)』 | |||||
注1: ここにはフットノート1が入る | |||||
注2: ここにはフットノート2が入る |
Markdown文法を使う場合は、文字列をmd()
関数内で指定することでMarkdown文として解釈されるようになる。
df1 |>
gt() |>
fmt_number(columns = 2:5, decimals = 3) |>
tab_header(title = "タイトル", subtitle = "サブタイトル") |>
tab_footnote(footnote = "注1: ここにはフットノート1が入る") |>
tab_footnote(footnote = "注2: ここにはフットノート2が入る") |>
tab_source_note(source_note = md("出典: 『[私たちのR](https://www.jaysong.net/RBook/)』")) |>
as_raw_html()
タイトル | |||||
サブタイトル | |||||
Variable | Mean | SD | Min | Max | Obs |
---|---|---|---|---|---|
出典: 『私たちのR』 | |||||
注1: ここにはフットノート1が入る | |||||
注2: ここにはフットノート2が入る |
グループ化
列をグループ化するためにはtab_spanner()
関数を使う。columns
引数にはグループ化する列の位置、もしくは名前を、label
にはグループ名を指定すれば良い。たとえば、df1
を使う場合、Min
とMax
列を一つのグループとしてRangeと名付けるとしよう。columns
は列の番号でも、列名でも良い。
df1 |>
gt() |>
tab_spanner(columns = 4:5, label = "Range") |>
fmt_number(columns = 2:5, decimals = 3) |>
as_raw_html()
Min | Max |
---|---|
続いて、行をグループ化する方法について紹介する。まず、df2
の中身を確認してみよう。
各大陸ごとの人口、面積などの情報が含まれている表であるが、これらを大陸単位で行をグループ化してみよう。方法は簡単だ。{dplyr}のようにgt()
関数に渡す前に、group_by()
でデータをグループ化すれば良い。今回はContinent
列の値に基づいてグループ化するため、group_by(Continent)
とする。
Variable | Mean | SD | Min | Max | Obs |
---|---|---|---|---|---|
Africa | |||||
America | |||||
Asia | |||||
Europe | |||||
Oceania | |||||
このようにグループ化することができる。引き続きMean
列からMax
列までの値を小数点3桁目で丸めてみよう。Mean
とMax
列の位置は2、5列目であるかのように見える。とりあえずやってみよう。
Variable | Mean | SD | Min | Max | Obs |
---|---|---|---|---|---|
Africa | |||||
America | |||||
Asia | |||||
Europe | |||||
Oceania | |||||
このようにエラーが表示される。なぜだろう。それはグルーピングに使用された変数も1つの列としてカウントされるからだ。つまり、グルーピングに使用されたContinent
列は列としては見えないものの、1列目として存在する。したがって、目に見える列番号に1を足す必要がある。それではグルーピングあと、Mean
列からMax
列までは小数点3桁目で丸め、Min
列とMax
列はRangeという名でグルーピングしてみよう。
df2 |>
group_by(Continent) |>
gt() |>
tab_spanner(columns = 5:6, label = "Range") |>
fmt_number(columns = 3:6, decimals = 3) |>
as_raw_html()
Min | Max | ||||
---|---|---|---|---|---|
Africa | |||||
America | |||||
Asia | |||||
Europe | |||||
Oceania | |||||
ややこしい話であるが、列を番号でなく、列名で指定すると、このような混乱を避けることができる。列の指定方法は好みの問題でもあるので、好きなやり方を使おう。
df2 |>
group_by(Continent) |>
gt() |>
tab_spanner(columns = Min:Max, label = "Range") |>
fmt_number(columns = Mean:Max, decimals = 3) |>
as_raw_html()
Min | Max | ||||
---|---|---|---|---|---|
Africa | |||||
America | |||||
Asia | |||||
Europe | |||||
Oceania | |||||
最後に、グルーピングとは関係ないものの、行の名前を指定する方法について説明する。それはgt()
で表を作成する際、行の名前にしたい列名をrowname_col
で指定すれば良い。たとえば、Variable
列を行の名前にしてみよう。
df2 |>
group_by(Continent) |>
gt(rowname_col = "Variable") |>
tab_spanner(columns = 5:6, label = "Range") |>
fmt_number(columns = 3:6, decimals = 3) |>
as_raw_html()
Min | Max | ||||
---|---|---|---|---|---|
Africa | |||||
Population | |||||
Area | |||||
GDP_per_capita | |||||
PPP_per_capita | |||||
HDI_2018 | |||||
Polity_Score | |||||
FH_Total | |||||
America | |||||
Population | |||||
Area | |||||
GDP_per_capita | |||||
PPP_per_capita | |||||
HDI_2018 | |||||
Polity_Score | |||||
FH_Total | |||||
Asia | |||||
Population | |||||
Area | |||||
GDP_per_capita | |||||
PPP_per_capita | |||||
HDI_2018 | |||||
Polity_Score | |||||
FH_Total | |||||
Europe | |||||
Population | |||||
Area | |||||
GDP_per_capita | |||||
PPP_per_capita | |||||
HDI_2018 | |||||
Polity_Score | |||||
FH_Total |