Rで解析:gridパッケージのプロットをお手軽に「gridExtra」パッケージの紹介
Rのgridグラフィックスは描画の自由度が高い一方、複数の図を1ページに並べたり、データフレームを表として描いたりする定型作業は自前で組む必要があります。gridExtraパッケージは、この手間のかかる作業をgtableベースのコマンド群で解決します。arrangeGrobとgrid.arrangeはlayout_matrixで各図の行と列を直接指定でき、marrangeGrobは図が多いときに自動で複数ページへ分割します。tableGrobはデータフレームや行列をそのまま表のグラフィックオブジェクトに変換し、ttheme_defaultで文字サイズや余白をまとめて制御できます。さらにngonGrobとellipseGrobで正多角形や楕円も描画可能です。gridオブジェクトのほか、ggplot2やlatticeのオブジェクトもグラフィックオブジェクトへ変換してくれます。
パッケージバージョンは2.3.1。Windows 11 x64 (build 26200)のR version 4.6.1で確認しています。
パッケージのインストール
下記コマンドを実行してください。
# パッケージのインストール
install.packages("gridExtra")
# パッケージの読み込み
library("gridExtra")
# コマンド例の実行に必要なパッケージの読み込み
library("grid")コマンド例
詳細はコメント、パッケージのヘルプを確認してください。
gridの世界では、描画される要素はすべてグラフィックオブジェクト(grob)として扱われます。gridExtraはこのgrobを対象に、複数のgrobを格子状に配置するarrangeGrob系、データフレームを表のgrobに変換するtableGrob系、正多角形や楕円のgrobを作るngonGrob系という3系統のコマンドを提供します。arrangeGrobやtableGrobはgtableオブジェクトを作成します。gtableオブジェクトはgrid.drawコマンドでプロットが可能です。
複数のグラフィックオブジェクトを1ページに配置:arrangeGrobコマンド
複数のgrobをレイアウト行列に従って配置したgtableを作成します。描画は行わないため、作成したgtableをgrid.drawに渡してプロットするか、さらに別のレイアウトの部品として使えます。
| オプション | 意味 | 初期値 |
|---|---|---|
| … | grob、gtable、ggplot、trellisのオブジェクトを可変長で指定 | なし |
| grobs | 配置するgrobのリストを指定 | list(…) |
| layout_matrix | 配置位置を表すレイアウト行列を指定(省略可) | なし |
| vp | 描画に用いるビューポートを指定 | NULL |
| name | gtableのname引数に渡す値 | “arrange” |
| as.table | 論理値、TRUEで左下から右上、FALSEで左上から右下の順に配置 | TRUE |
| respect | gtableのrespect引数に渡す値 | FALSE |
| clip | gtableのclip引数に渡す値 | “off” |
| nrow | gtableのnrow引数に渡す値で行数を指定 | NULL |
| ncol | gtableのncol引数に渡す値で列数を指定 | NULL |
| widths | gtableのwidths引数に渡す値で各列の幅を指定 | NULL |
| heights | gtableのheights引数に渡す値で各行の高さを指定 | NULL |
| top | 上側に配置する文字列またはgrobを指定(省略可) | NULL |
| bottom | 下側に配置する文字列またはgrobを指定(省略可) | NULL |
| left | 左側に配置する文字列またはgrobを指定(省略可) | NULL |
| right | 右側に配置する文字列またはgrobを指定(省略可) | NULL |
| padding | 注釈の周囲に確保する余白を長さ1のunitで指定 | unit(0.5, “line”) |
### データ例を作成#####
# パネルに表示するラベル
panel_label <- c("Site-A", "Site-B", "Site-C", "Site-D")
# パネルの背景色
panel_fill <- c("#F7D6A0", "#BFD8C4", "#C7CDE8", "#EBC6C6")
# 背景の矩形とラベル文字を重ねたgrobをリストとして作成
panel_list <- mapply(function(lab, bg) {
grobTree(rectGrob(gp = gpar(fill = bg, col = "white", lwd = 2)),
textGrob(lab, gp = gpar(fontsize = 14)))},
panel_label, panel_fill, SIMPLIFY = FALSE)
########
# 1番目を上段全幅、2番目と3番目を中段に並べ、4番目を下段全幅にするレイアウト行列を作成
panel_layout <- rbind(c(1, 1), c(2, 3), c(4, 4))
# レイアウト行列に従って配置したgtableを作成(この時点では描画されない)
g_arrange <- arrangeGrob(grobs = panel_list,
layout_matrix = panel_layout,
top = "arrangeGrob layout",
padding = unit(1, "line"))
# 新しい描画ページを用意
grid.newpage()
# 作成したgtableを描画
grid.draw(g_arrange)
配置したレイアウトをプロット:grid.arrangeコマンド
arrangeGrobと同じ引数を受け取り、作成したgtableをプロットします。
| オプション | 意味 | 初期値 |
|---|---|---|
| … | arrangeGrobに渡すgrobおよび引数を可変長で指定 | なし |
| newpage | 論理値、TRUEで新しいページを開いてから描画 | TRUE |
# 3つの矩形grobを1行に並べ、上下に見出しを付けてプロット
grid.arrange(rectGrob(gp = gpar(fill = "#F2C14E", col = NA)),
rectGrob(gp = gpar(fill = "#78B7A0", col = NA)),
rectGrob(gp = gpar(fill = "#8FA6D8", col = NA)),
nrow = 1,
top = "grid.arrange",
bottom = "three panels in one row",
newpage = TRUE)
# widthsで幅の比率を2対1に変えてプロット(列数はwidthsで決まる)
grid.arrange(rectGrob(gp = gpar(fill = "#F2C14E", col = NA)),
rectGrob(gp = gpar(fill = "#78B7A0", col = NA)),
widths = c(2, 1),
newpage = TRUE)・3つの矩形grobを1行に並べ、上下に見出しを付けてプロット

・widthsで幅の比率を2対1に変えてプロット(列数はwidthsで決まる)

複数ページに分割して配置:marrangeGrobコマンド
grobの個数が1ページに配置できる数を超える場合、同じレイアウトを繰り返し適用してページ単位に分割しプロットします。
| オプション | 意味 | 初期値 |
|---|---|---|
| grobs | 配置するgrobのリストを指定 | なし |
| … | arrangeGrobに渡す引数を可変長で指定 | なし |
| ncol | 1ページあたりの列数を指定 | なし |
| nrow | 1ページあたりの行数を指定 | なし |
| layout_matrix | 1ページ分の配置位置を表すレイアウト行列を指定 | matrix(seq_len(nrow * ncol), nrow = nrow, ncol = ncol) |
| top | 各ページ上部に表示する見出しを式または文字列で指定 | quote(paste(“page”, g, “of”, npages)) |
# 6枚分のgrobをオリジナルデータとして作成
page_grobs <- lapply(1:6, function(i) {
grobTree(rectGrob(gp = gpar(fill = "grey95", col = "grey60")),
textGrob(paste0("panel ", i), gp = gpar(fontsize = 14)))})
# 1ページあたり2行2列で分割した配置リストを作成
g_multi <- marrangeGrob(page_grobs, nrow = 2, ncol = 2)
# 分割されたページ数を確認
length(g_multi)
# 新しい描画ページを用意
grid.newpage()
# 1ページ目を描画
grid.draw(g_multi[[1]])
# 新しい描画ページを用意
grid.newpage()
# 2ページ目を描画
grid.draw(g_multi[[2]])・1ページ目を描画

・2ページ目を描画

正多角形を描画する:ngonGrobコマンド
中心座標と頂点数を指定して、単位円に内接する正多角形のgrobを作成します。頂点数や大きさ、回転角、縦横比はベクトルで与えることができ、その場合は中心座標の個数に合わせて繰り返し適用されます。作成と描画を同時に行うgrid.ngonコマンドも収録されています。
| オプション | 意味 | 初期値 |
|---|---|---|
| x | 図形の中心のx座標をunitで指定 | なし |
| y | 図形の中心のy座標をunitで指定 | なし |
| n | 頂点の数を指定 | 5 |
| size | 外接円の半径を指定 | 5 |
| phase | 最初の頂点のx軸からの角度をラジアンで指定 | pi/2 |
| angle | 多角形全体の回転角をラジアンで指定 | 0 |
| ar | 縦横比を指定 | 1 |
| gp | 線と塗りつぶしの書式をgparで指定 | gpar(colour = “black”, fill = NA, linejoin = “mitre”) |
| … | polygonGrobに渡す追加の引数を指定 | なし |
| position.units | 座標に用いる既定の単位を指定 | “npc” |
| size.units | 大きさに用いるgridの単位を指定 | “mm” |
# 描画する正多角形の頂点数をオリジナルデータとして作成
ngon_n <- c(3, 4, 6, 8)
# 図形を並べるx座標を等間隔で作成
ngon_x <- seq(0.15, 0.85, length.out = length(ngon_n))
# 図形の塗りつぶし色を作成
ngon_col <- c("#E29578", "#83C5BE", "#F4D06F", "#8FA6D8")
# 頂点数の異なる正多角形をまとめた1つのgrobを作成
g_ngon <- ngonGrob(x = unit(ngon_x, "npc"),
y = unit(rep(0.5, length(ngon_n)), "npc"),
n = ngon_n,
size = 12,
gp = gpar(fill = ngon_col, col = "grey20"))
# 新しい描画ページを用意
grid.newpage()
# 正多角形のgrobを描画
grid.draw(g_ngon)
# 同じ配置に回転角と縦横比の変化を加えたgrobを作成
g_ngon_var <- ngonGrob(x = unit(ngon_x, "npc"),
y = unit(rep(0.5, length(ngon_n)), "npc"),
n = ngon_n,
size = 12,
angle = seq(0, pi / 2, length.out = length(ngon_n)),
ar = c(1, 0.5, 2, 1),
gp = gpar(fill = ngon_col, col = "grey20"))
# 新しい描画ページを用意
grid.newpage()
# 回転と縦横比を変えたgrobを描画
grid.draw(g_ngon_var)
########
# 新しい描画ページを用意
grid.newpage()
# grid.ngonを使うとgrobの作成と描画を一度に実行できる
grid.ngon(x = unit(0.5, "npc"), y = unit(0.5, "npc"),
n = 7, size = 30, gp = gpar(fill = "#83C5BE", col = "grey20"))・正多角形のgrobを描画

・回転と縦横比を変えたgrobを描画

・grid.ngonを使うとgrobの作成と描画を一度に実行できる

楕円をプロット:ellipseGrobコマンド
n個の頂点で円を近似したうえでarとangleにより変形させた楕円のgrobを作成します。arで扁平の度合いを、angleで傾きを指定します。作成と描画を同時に行うgrid.ellipseも用意されています。
| オプション | 意味 | 初期値 |
|---|---|---|
| x | 楕円の中心のx座標をunitで指定 | なし |
| y | 楕円の中心のy座標をunitで指定 | なし |
| size | 外接円の半径を指定 | 5 |
| angle | 楕円全体の回転角をラジアンで指定 | pi/4 |
| ar | 縦横比を指定 | 1 |
| n | 楕円の近似に用いる頂点の数を指定 | 50 |
| gp | 線と塗りつぶしの書式をgparで指定 | gpar(colour = “black”, fill = NA, linejoin = “mitre”) |
| … | polygonGrobに渡す追加の引数を指定 | なし |
| position.units | 座標に用いる既定の単位を指定 | “npc” |
| size.units | 大きさに用いるgridの単位を指定 | “mm” |
# 楕円の中心のx座標
ell_x <- c(0.25, 0.50, 0.75)
# 楕円の中心のy座標
ell_y <- c(0.35, 0.60, 0.35)
# 楕円の傾き
ell_angle <- c(pi / 6, 0, -pi / 6)
# 傾きと扁平の度合いを指定した楕円のgrobを作成
g_ellipse <- ellipseGrob(x = unit(ell_x, "npc"),
y = unit(ell_y, "npc"),
size = 22,
ar = 0.35,
angle = ell_angle,
gp = gpar(fill = c("#E29578", "#83C5BE", "#8FA6D8"),
col = "grey20"))
# 新しい描画ページを用意
grid.newpage()
# 楕円のgrobを描画
grid.draw(g_ellipse)
########
# 新しい描画ページを用意
grid.newpage()
# grid.ellipseを使うとgrobの作成と描画を一度に実行できる
grid.ellipse(x = unit(0.5, "npc"), y = unit(0.5, "npc"),
size = 35, ar = 2, angle = pi / 3,
gp = gpar(fill = "#F4D06F", col = "grey20"))・楕円のgrobを描画

正多角形の頂点座標を取得:polygon_regularコマンド
単位円に内接する正多角形の頂点座標を2列の行列として返します。始点と終点が同じ座標になるため、行数は頂点数に1を加えた値になります。ngonGrobの内部でも使われており、座標を自分で加工したい場合に便利です。
| オプション | 意味 | 初期値 |
|---|---|---|
| n | 頂点の数を指定 | 5 |
| phase | 最初の頂点のx軸からの角度をラジアンで指定 | 0 |
# 単位円に内接する正六角形の頂点座標を取得
hex_xy <- polygon_regular(n = 6)
# 取得した座標を確認(始点と終点が同じ座標になり閉じた形になる)
hex_xy
[,1] [,2]
[1,] 6.123032e-17 1.0
[2,] -8.660254e-01 0.5
[3,] -8.660254e-01 -0.5
[4,] -1.836910e-16 -1.0
[5,] 8.660254e-01 -0.5
[6,] 8.660254e-01 0.5
[7,] 3.061516e-16 1.0
# 行数と列数を確認
dim(hex_xy)
# 開始角度を30度ずらした正六角形の頂点座標を取得
hex_rot <- polygon_regular(n = 6, phase = pi / 6)
# 取得した座標を確認
hex_rot
[,1] [,2]
[1,] -0.5 8.660254e-01
[2,] -1.0 3.330669e-16
[3,] -0.5 -8.660254e-01
[4,] 0.5 -8.660254e-01
[5,] 1.0 -7.216450e-16
[6,] 0.5 8.660254e-01
[7,] -0.5 8.660254e-01データフレームを表としてプロット:tableGrobコマンド
データフレームや行列の各セルを文字のgrobに変換し、格子状に並べたgtableを返します。rowsやcolsにNULLを渡すと行名や列名の行を省略できます。作成と描画を同時に行うgrid.tableも用意されています。
| オプション | 意味 | 初期値 |
|---|---|---|
| d | 表として描画するデータフレームまたは行列を指定 | なし |
| rows | 行名として表示するベクトルを指定(省略可) | rownames(d) |
| cols | 列名として表示するベクトルを指定(省略可) | colnames(d) |
| theme | 表の書式をまとめたテーマのリストを指定 | ttheme_default() |
| vp | 描画に用いるビューポートを指定(省略可) | NULL |
| … | gtableの制御に用いる追加の引数を指定 | なし |
# 表データを作成
obs_data <- data.frame(site = c("Kyoto", "Shiga", "Tokyo"),
temp = c(21.4, 20.8, 19.6),
rain = c(112.5, 98.0, 143.2),
stringsAsFactors = FALSE)
# データフレームをそのまま表のgtableに変換
g_table <- tableGrob(obs_data)
# 新しい描画ページを用意
grid.newpage()
# 表のgtableを描画
grid.draw(g_table)
########
# 行名を省略し、列名を任意の文字列に置き換えた表のgtableを作成
g_table_named <- tableGrob(obs_data,
rows = NULL,
cols = c("Site", "Temp (C)", "Rain (mm)"))
# 新しい描画ページを用意
grid.newpage()
# 列名を差し替えた表を描画
grid.draw(g_table_named)
# 新しい描画ページを用意
grid.newpage()
# grid.tableを使うと表の作成と描画を一度に実行できる
grid.table(obs_data, rows = NULL)
表の書式をまとめて指定:ttheme_defaultコマンド
tableGrobのthemeに渡す書式のリストを作成します。文字サイズ、文字色、フォントファミリー、セル内の余白をまとめて指定でき、返り値のリストを直接書き換えて個別の要素を上書きすることもできます。背景の塗りつぶしと罫線を持たないttheme_minimalも同じ引数構成で用意されています。
コマンド例内のobs_dataは先のtableGrobコマンドの例で作成します。
| オプション | 意味 | 初期値 |
|---|---|---|
| base_size | 既定の文字サイズを指定 | 12 |
| base_colour | 既定の文字色を指定 | “black” |
| base_family | 既定のフォントファミリーを指定 | “” |
| parse | 論理値、TRUEで文字列をplotmathの式として解釈 | FALSE |
| padding | セル内の水平方向と垂直方向の余白を長さ2のunitで指定 | unit(c(4, 4), “mm”) |
| … | テーマの各要素を上書きする追加の引数を指定 | なし |
# 文字サイズと文字色、セル内の余白を変更したテーマを作成
my_theme <- ttheme_default(base_size = 10,
base_colour = "#20304A",
padding = unit(c(6, 3), "mm"))
# 作成したテーマを適用した表のgtableを作成
g_theme <- tableGrob(obs_data, rows = NULL, theme = my_theme)
# 新しい描画ページを用意
grid.newpage()
# テーマを適用した表を描画
grid.draw(g_theme)
########
# 背景と罫線を持たない最小限のテーマを適用した表のgtableを作成
g_minimal <- tableGrob(obs_data, rows = NULL,
theme = ttheme_minimal(base_size = 10))
# 新しい描画ページを用意
grid.newpage()
# 最小限のテーマを適用した表を描画
grid.draw(g_minimal)複数の表を結合する:gtable_rbindコマンド
複数のgtableを縦方向に結合します。列数が一致している必要があり、列幅はsizeの指定に従ってそろえられます。横方向に結合するgtable_cbindも同じ引数構成で、こちらは行数が一致している必要があります。行名や列名を手がかりに位置合わせをしてから結合するgtable_combineも用意されています。
| オプション | 意味 | 初期値 |
|---|---|---|
| … | 結合するgtableを可変長で指定 | なし |
| size | 幅と高さの決め方を”max”、”min”、”first”、”last”から指定 | “max” |
| z | 重ね合わせ順序を表すz値を指定(省略可) | NULL |
# 上側に置く表のgtableを作成
tbl_upper <- tableGrob(obs_data[1:2, ], rows = NULL,
theme = ttheme_default(base_size = 10))
# 下側に置く表のgtableを作成
tbl_lower <- tableGrob(obs_data[3, ], rows = NULL, cols = NULL,
theme = ttheme_minimal(base_size = 10))
# 2つの表を縦方向に結合し、列幅は最大値にそろえる
g_rbind <- gtable_rbind(tbl_upper, tbl_lower, size = "max")
# 新しい描画ページを用意
grid.newpage()
# 縦方向に結合した表を描画
grid.draw(g_rbind)
########
# 左側に置く表のgtableを作成
tbl_left <- tableGrob(obs_data[, c("site", "temp")], rows = NULL,
theme = ttheme_default(base_size = 10))
# 右側に置く表のgtableを作成
tbl_right <- tableGrob(obs_data[, "rain", drop = FALSE], rows = NULL,
theme = ttheme_default(base_size = 10))
# 2つの表を横方向に結合し、行の高さは最大値にそろえる
g_cbind <- gtable_cbind(tbl_left, tbl_right, size = "max")
# 新しい描画ページを用意
grid.newpage()
# 横方向に結合した表を描画
grid.draw(g_cbind)・縦方向に結合した表を描画

この記事が誰かの役に立ちますように。