gt パッケージの紹介 ~Rで作表の決定版!?~ (2)
Rで綺麗な表を作成するgtパッケージ紹介の第2段です。
前回の記事では、gtパッケージの概要と作表の大まかな流れを紹介しました。 kur0cky.hatenablog.com
今回は、実際に表をカスタマイズするときに使う様々な関数を整理し、より細かな作業を紹介します。
gtパッケージの関数群の整理
公式のリファレンスに整理されていることではありますが、gtパッケージの関数はいくつかのグループに分けることができます。
本記事では特に、gtテーブルの各パーツ(ヘッダやレコードのグルーピングなど)を作成するfmt_**()
関数を中心に紹介します。
gt()
,gt_preview()
:gt_tbl
オブジェクトの作成。gt_preview()
では先頭と末尾を(デフォルトでは)5行ずつ表示するオブジェクトを作成します。
tab_***()
:- 前の記事で紹介したgtの表の各要素を追加するような関数群です。たとえば、ヘッダーやフッターの作成、行や列ごとのグルーピングを行うことができます。
fmt_***()
:- セルの値の見栄えをよくするような関数群です。たとえば、datetimeのフォーマットを一括で修正したり、欠損
NA
を-
で一括置換することができます。
- セルの値の見栄えをよくするような関数群です。たとえば、datetimeのフォーマットを一括で修正したり、欠損
cols_***()
:- カラム(変数)全体の変更を行うような関数群です。たとえば、カラムの順序を入れ替えたり名前の変更、2つのカラムの結合などを行うことができます。
- 行変更関数:
- 現在はテーブル内の任意の行グループの順序を変更することができる
row_group_order()
や、集計行を追加するsummary_rows()
,grand_summary_rows()
があります。
- 現在はテーブル内の任意の行グループの順序を変更することができる
***_image()
:- gtパッケージでは表のセル中に画像を挿入することができます。なんとggplotオブジェクトも
ggplot_image()
で入れることができます。
- gtパッケージでは表のセル中に画像を挿入することができます。なんとggplotオブジェクトも
opt_***()
:- よく使われる表オプションを簡単に設定することができます。たとえば、 脚注で使うマークのセットを変更したり、行の縞模様を有効にしたり、表ヘッダのアラインメントを変更したりすることができます。
info_***
:- 有用な情報を含むgtテーブルを表示してくれる関数群です。gtがサポートする日付スタイルや時刻スタイル、カラーパレット、通貨、ロケールについての参照情報を得ることができます。ここを参照することで、たとえば表示させたいdatetimeのフォーマットなどにすぐアクセスすることができます。
- ヘルパー関数:
- 表内でマークダウン表記を使うための
md()
や数値をパーセンテージで扱うためのpct()
など、便利な細々とした関数群です。
- 表内でマークダウン表記を使うための
gtテーブルの各パーツの作成
まずはライブラリを読み込みます
library(tidyverse) library(gt)
今回は誰もが知っているirisデータを使った、次の集計を表にしたいと思います。
df <- iris %>% gather(var, value, -Species) %>% group_by(Species, var) %>% summarise(q1 = quantile(value, .25), median = median(value), q3 = quantile(value, .75), mean = mean(value), sd = sd(value)) %>% ungroup() df
# A tibble: 12 x 7 Species var q1 median q3 mean sd <fct> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> 1 setosa Petal.Length 1.4 1.5 1.58 1.46 0.174 2 setosa Petal.Width 0.2 0.2 0.3 0.246 0.105 3 setosa Sepal.Length 4.8 5 5.2 5.01 0.352 4 setosa Sepal.Width 3.2 3.4 3.68 3.43 0.379 5 versicolor Petal.Length 4 4.35 4.6 4.26 0.470 6 versicolor Petal.Width 1.2 1.3 1.5 1.33 0.198 7 versicolor Sepal.Length 5.6 5.9 6.3 5.94 0.516 8 versicolor Sepal.Width 2.52 2.8 3 2.77 0.314 9 virginica Petal.Length 5.1 5.55 5.88 5.55 0.552 10 virginica Petal.Width 1.8 2 2.3 2.03 0.275 11 virginica Sepal.Length 6.22 6.5 6.9 6.59 0.636 12 virginica Sepal.Width 2.8 3 3.18 2.97 0.322
最終的には下のようなな表を作っていきます。
Edgar Anderson's Iris Data | |||||
---|---|---|---|---|---|
the most famous dataset | |||||
Petal.Length | |||||
Petal.Width | |||||
Sepal.Length | |||||
Sepal.Width | |||||
Source: Fisher, R. A. (1936) The use of multiple measurements in taxonomic problems. Annals of Eugenics, 7, Part II, 179–188. | |||||
1
標準偏差が0.4以上
|
gtテーブルの作成:
最も基本となる、そもそものテーブルオブジェクトの作成はgt()
で行います。これだけでも十分綺麗な表が出力できています。
df %>% gt()
gt()
では、行名を示すカラムのオプションrowname_col
、グループを示すカラムのオプションgroupname_col
などを指定することができます。ここでは、どちらも指定してみましょう。
df %>% gt(rowname_col = "Species", groupname_col = "var")
Petal.Length | |||||
Petal.Width | |||||
Sepal.Length | |||||
Sepal.Width | |||||
タイトルの設定
タイトルやサブタイトルはtab_header()
で追加することができます
df %>% gt() %>% tab_header(title = "Edgar Anderson's Iris Data", subtitle = "the most famous dataset")
Edgar Anderson's Iris Data | ||||||
---|---|---|---|---|---|---|
the most famous datset | ||||||
リファレンスの追加
gtではtab_source_note()
によってフッターにリファレンスを追加することができます。irisデータのソースであるFisherの論文を引用してみましょう。
また、gtテーブルの各部分では、md()
によって、マークダウン記法を用いることもできます。雑誌名を斜体で、巻号を太字で書きてみます。
df %>% gt() %>% tab_source_note(source_note = md("Source: Fisher, R. A. (1936) The use of multiple measurements in taxonomic problems. *Annals of Eugenics*, **7**, Part II, 179–188."))
Source: Fisher, R. A. (1936) The use of multiple measurements in taxonomic problems. Annals of Eugenics, 7, Part II, 179–188. |
列のグルーピング
gtでは変数をグルーピングすることができ、そのグループをスパナと呼びます。ここでは、第一四分位、中央値、第三四分位をパーセンタイルとしてグルーピングします。
まとめる変数の指定columns
では、dplyrと同じように、vars()
を使うことができます。
df %>% gt() %>% tab_spanner(label = "percentile", columns = vars(q1, median, q3))
行のグルーピング
行のグルーピングにはtab_row_group()
を用います。グループにする行の指定rows
には、数値ベクトルを指定することができますが、以下のgt(rowname_col = "Species")
のように行名が指定してある場合、dplyr::select()
と同様にヘルパー関数を使うことができます。便利ですね。
df %>% gt(rowname_col = "Species") %>% tab_row_group(group = "vからはじまる種類", rows = starts_with("v"), others = "その他")
vからはじまる種類 | ||||||
その他 | ||||||
脚注の追加
tab_footnote()
によって脚注を追加することができます。
どの部分に脚注をつけるかはlocations
オプションで指定しますが、ここではヘルパー関数cells_***()
を使うことができます。
ここでは、標準偏差sdが0.4を超えるところに脚注をつけてみましょう。表の本体 body につけたいので、ヘルパー関数はcells_body()
を使います。cells_body(columns = vars(sd), rows = sd > 0.4)
としました。このように、条件で脚注をつける箇所を指定することができるため、たとえば「p値が有意となるものに印をつけたい」といった場合に非常に有用です。
df %>% gt() %>% tab_footnote( footnote = "標準偏差が0.4以上", locations = cells_body( columns = vars(sd), rows = sd > 0.4))
1
標準偏差が0.4以上
|
組み合わせる
それでは、上記のtab_***()
をブロックのように組み合わせて、冒頭の表を作ります。
df %>% gt(groupname_col = "var", rowname_col = "Species") %>% tab_header(title = "Edgar Anderson's Iris Data", subtitle = "the most famous dataset") %>% tab_source_note(source_note = md("Source: Fisher, R. A. (1936) The use of multiple measurements in taxonomic problems. *Annals of Eugenics*, **7**, Part II, 179–188.")) %>% tab_spanner(label = "percentile", columns = vars(q1, median, q3)) %>% tab_footnote( footnote = "標準偏差が0.4以上", locations = cells_body( columns = vars(sd), rows = sd > 0.4)) %>% tab_footnote( footnote = "ヒオウギアヤメ。アヤメ科アヤメ属に分類される多年草", locations = cells_body( columns = vars(Species), rows = Species == "setosa"))
以上、gtパッケージの基本的な作表関数を紹介しました。
gt パッケージの紹介 ~Rで作表の決定版!?~ (1)
Rで綺麗な表を作るパッケージgtの存在を知りました。神ライブラリの予感がしたので少し調べたり触ったりしてたことをまとめます。
いままではknitr::kable()
やDT::datatable()
を使っていたのですが、本格的に乗り換えを検討しています。
gtパッケージとは
- Rで綺麗な表を作るライブラリ。
- DTパッケージとは異なり、インタラクティブな操作はできな。
- 作図におけるggplot2的ポジションを狙っていると思われる。
- tidyverseのスタイルガイドに準拠しており、パイプ演算子
%>%
を用いて、細かい表の調整をブロックのように組み合わせることができる。
gtパッケージで作れる表の形
gtパッケージを使うとどのような表をつくることができるか、公式サイトから図を拝借させていただきました。
図より、表が以下の要素から構成されていることがわかります。table body以外は必ずしも付ける必要はなく、場合に応じて付け足していくことになります。
- table body : 表の本体。値が入る部分
- table header : ヘッダー。タイトルとサブタイトル
- table footer : フッター。注釈やリファレンスなど
- column labels : 列名。複数列に対してラベルをつけることもできる
- stub : 行名。インデックス
- stub head : 行名の上にくる部分
基本的な流れ
- 表にするデータフレームの用意
data.frame
,tibble
,data.table
のいずれでも良い。
gt()
によるgt_tbl
オブジェクト作成- 細々した調整
- 出力。保存など。
- なんとhtml形式だけでなく、latex形式でも作れる!!
gtテーブルオブジェクトの作成:gt()
データフレームを用意し、gt()
に渡すことで行います。
# CRANに登録されているのでインストールは install.packages("gt") library(tidyverse) library(gt) df <- iris %>% group_by(Species) %>% summarise(count = n(), mean_SepalLength = mean(Sepal.Length), sd_SepalLength = sd(Sepal.Length)) tbl_1 <- gt(df) print(tbl_1)
すると、以下のような表が作成されます。この時点でも十分綺麗ですね。
どんどんリッチにすることができます。たとえばtab_header()
を使ってタイトルを付け加えてみます。まるでggplotのように、表のオプションをパイプでつなげていくことができます。
tbl_2 <- tbl_1 %>% tab_header(title = "Edgar Anderson's Iris Data", subtitle = "The species are Iris setosa, versicolor, and virginica") tbl_2
Edgar Anderson's Iris Data | |||
---|---|---|---|
The species are Iris setosa, versicolor, and virginica | |||
様々なgtの関数や使い方はまた次の記事で紹介しようと思います。
表の出力
ggplotと同様、Rmd中やConsole上であればgt_tbl
オブジェクトをそのままprint()
することで表示することができますが、表のhtmlファイルを別で保存するには、gtsave()
関数を使います。次のコードでは上で作った表をiris_summary.html
という名前で保存しています。
gtsave(tbl_2, "iris_summary.html")
なんと、gtsave()
の中のファイル名で、拡張子を.tex
とすると、LaTeX形式で保存することもできます。これで、面倒だったmulticolumnやmultirowなどに悩まされることもなくなるでしょう!!すごい!!
ネットワーククラスタリングについて (1)
大学院での研究では、一部ネットワークにまつわるものをやっていました。ネットワークといっても通信の方ではなく、ノードとエッジから構成されるグラフの方です。 最近は、ネットワークの構造に基づいてノードを教師なしで分類していくネットワーククラスタリングに興味があり、備忘録がてらまとめていきます。また、ここでは簡単のため重複エッジや自己ループを許さない無向グラフのみを対象とします。
0. コミュニティとは
ネットワーク科学では、ノードのクラスタのことをしばしば「コミュニティ」とよびます。人間や企業などの主体をノードとして扱うことが多いからかもしれません。コミュニティの定義は難しそうですが、感覚的な特徴には以下のようなものが考えられます。
- コミュニティ内では繋がりが密である
- 大きなネットワークの一部分である
- コミュニティ外のノードとよりも、コミュニティ内との繋がりが強い
このような感覚的な表現を出発として、コミュニティを表すような様々な概念が定義されてきました。
1. クリーク
「大きなネットワークの一部分では、その全てのノード同士が結びついている」
このような状況は、コミュニティとみなすのに易いでしょう。このような部分グラフを、クリークといいます。クリークを以下で定義します。ここで「極大である」とは、クリーク内のすべてのノードと接続しているノードがクリーク外に存在しないことを意味します。
クリーク:極大である完全誘導部分グラフ
ネットワークにおいて三角形はよく見られますが、大規模なクリークを発見することは難しいでしょう。ノード数が増えたときは「完全部分グラフ」であることが難しくなるため、様々なクリークの条件を緩和することが考えられてきました。
2. クリークの条件緩和
クリークよりも弱いものを紹介します。
- -クラン:含まれる任意のノードどうしの距離が以下であるような極大誘導部分グラフ。直径が以下となります
- -クラブ:-クランのうち、直径がであるもの
- -プレックス:含まれるどの頂点の次数も以上である極大誘導部分グラフ
- -コア:どの頂点の次数もを下回らない誘導部分グラフ。-プレックスのがクリークとの差を表すのに対し、-コアのは絶対的な次数です
また、ネットワークのノード数や密度は様々であるため、コミュニティ内とコミュニティ外の相対的な割合をみる強いコミュニティと弱いコミュニティが知られています。
準備として、個ノードで構成されるネットワークの部分グラフのノード集合をとする。また、の隣接行列をとします。 の要素は、ノードが接続されているとき1、接続されていないとき0です。 ここで、ノードが部分グラフに対して持つ内部次数と外部次数を定義します。 自体が部分グラフに属しているかどうかは関係ないことに注意が必要です。
- 内部次数:
- 外部次数:
内部次数と外部次数を用いて弱いコミュニティ、強いコミュニティは次のように定義されます。
- 強いコミュニティ:コミュニティ内の任意のノードで
- 弱いコミュニティ:
3. 凝集性 (cohesion)
強いコミュニティ・弱いコミュニティは「コミュニティとみなせるか否か」を与える定義ですが、「コミュニティになっている程度」を連続値として与える凝集性という指標がしられています。ここで、は部分グラフ内のノード数とします。
- 凝集性:
凝集性は(部分グラフ内での密度) / (部分グラフ内から部分グラフ外に対する密度)で表されているため、「凝集性が1以上であれば、また大きければ大きいほど、部分グラフは外部と区別でき、コミュニティの傾向をもっている」と解釈することができます。
4. モジュラリティ
以上では、1つのコミュニティのあり方について、様々な定義や程度の指標を見てきました。実際のネットワーククラスタリングでは、ネットワーク全体を複数のクラスタに分けることを行います。このような問題はグラフ分割とよばれることがあり、特にモジュール数が自動的に決定されるようなタスクをコミュニティ検出といったりします。妥当なクラスタリングを行うためには「分割の質の良さ」を測る必要がありますが、特に有名な指標としてモジュラリティ (modurality)が知られています。
モジュラリティの根底にあるアイデアは、「ランダムグラフはコミュニティ構造をもたない」というものです。コミュニティの特徴をもう一度振り返ると、「部分グラフ内に張られるリンクの割合がそれ以外よりも多い」ことが重要でした。つまり、与えられた分割に対して、「グループ内で張られているエッジの割合」と「エッジがランダムに張られた場合の期待値」との差が重要になります。
いま、ネットワークを個の部分グラフに分割し、部分グラフ間に張られるエッジ数の割合を要素にもつの行列を用意します。つまり、の要素はとなります。 の対角成分は分割されたグループ内で張られるエッジの割合であり、非対角成分は異なるグループ間で張られるエッジの割合です。 また、グループ に接続するエッジの割合を考えると、の行和となります。
もしネットワークが完全にランダムであり、コミュニティ構造を持たないなら、はで独立になるため、それぞれの行和の積と期待されます。 よって、「グループ内で張られているエッジの割合」と「エッジがランダムに張られた場合の期待値」との差を表すモジュラリティ指標は次式で定義することができます。
- モジュラリティ:
大規模なネットワークではモジュラリティを最大化する厳密解を得るのは困難ですが、近似解を得るような様々なアルゴリズムが存在します。