【R】【ggplot2】facet_gridの各パネルに直線や領域を設定する方法
ggplot2でのfacet_grid()
使用時に、それぞれのパネルごとに直線(geom_segment
)や塗りつぶし領域(geom_rect
)を設定して描画する方法です。
解決策は一言で書くととてもシンプル。
「geon_segment()
やgeom_rect()
で指定するデータにも、facet_grid()
で使った要因と同じものを変数として用意しておくだけ」です。
以下、プログラム例です。
permutation testで実測値とシミュレーション値の比較結果を図示したいときなどに使えるかも。
目次
環境
- Mac
- R
- R Studio
- Tidyverseパッケージ
ダミーデータ生成
まずは乱数生成関数を使い、ダミーのデータセットdf_data
を作成します。
df_data <- data.frame(
x = rnorm(1000, mean = 0, sd = 2), #平均0、標準偏差2
y = rnorm(1000, mean = 0.3, sd = 1.5), #平均0.3、標準偏差1.5
z = rnorm(1000, mean = -0.2, sd = 1) #平均-0.2、標準偏差1
) %>%
pivot_longer(
cols = everything(),
names_to = "Variable",
values_to = "sample"
)
これで、このような構造のデータフレームができます。
Variable sample
x 1.3785482
y -0.5488806
z -2.0488779
x -2.5268924
y 1.3306550
z -0.4958901
# 以下、省略
x,y,zそれぞれに、平均と標準偏差が異なる正規分布に従うデータが1000個ずつ入っています。
以下、このデータをベースにグラフを描いていきます。
基本のプロット
まずは、TidyVerseパッケージに含まれるggplot2パッケージでヒストグラムを描いてみます。
#最初にパッケージを読み込む
library(tidyverse) #インストール済みと想定
その際、facet_grid()
で変数x,y,zのデータを別々のパネルに分けて描画します。
df_data %>%
ggplot() +
geom_histogram(aes(x = sample)) + #ヒストグラム
facet_grid(~ factor(Variable)) + #x,y,zのデータを別々のパネルに
theme_classic() + #自分好みの設定
theme( #自分好みの設定
strip.background = element_rect(linewidth = 0.5),
strip.placement = "outside",
panel.spacing = unit(1, "lines")
)
そうすると、このようなグラフが出力されます。
直線を追加する
次に、上で描画した基本のヒストグラムに、実測値データの場所を直線で追加したいといった場合は、以下のようにします。
たとえば、
- パネルxでは、sample = -3.8
- パネルyでは、sample = -6.0
- パネルzでは、sample = 0.0
に直線を引きたいとします。
そのときはまず、以下のようなデータフレームdf_real_data
を作成します。
#facet_gird()で指定した要因と同じものを変数として追加するのが肝
df_real_data <- data.frame(
Variable = c("x", "y", "z"), #肝
sample = c(-3.8, -6.0, 0.0)
)
geom_vline() ver.
ただ直線を引けばいいという時は、geom_vline()
を使います。
df_data %>%
ggplot() +
geom_histogram(aes(x = sample)) + #ヒストグラム
geom_vline( #ここが追加部分
data = df_real_data, #先ほど作成したデータを指定
aes(xintercept = sample, colour = "orange")
) +
facet_grid(~ factor(Variable)) + #x,y,zのデータを別々のパネルに
theme_classic() + #自分好みの設定
theme( #自分好みの設定
strip.background = element_rect(linewidth = 0.5),
strip.placement = "outside",
panel.spacing = unit(1, "lines"),
legend.position = "none" #ここも追加(vlineの色が凡例として表示されないように)
)
そうすると、このようなグラフが出力されます。(sampleの値がオレンジ色の直線で表示されています)
geom_segment() ver.
上記の「geom_vline() ver.」では、y = 0
を貫通して直線が引かれます。なので、見た目のために、直線の範囲をy = 0
からにしたい場合もあると思います。
そんなときは、geom_segment()
で線を引く範囲を指定すればOK。
df_data %>%
ggplot() +
geom_histogram(aes(x = sample)) + #ヒストグラム
geom_segment( #変更部分。yendは、元データから適当に設定
data = df_real_data, #先ほど作成したデータを指定
aes(x = sample, xend = sample, y = 0, yend = 180, colour = "orange")
) +
facet_grid(~ factor(Variable)) + #x,y,zのデータを別々のパネルに
theme_classic() + #自分好みの設定
theme( #自分好みの設定
strip.background = element_rect(linewidth = 0.5),
strip.placement = "outside",
panel.spacing = unit(1, "lines"),
legend.position = "none"
)
このようなグラフが出力されます。
領域を追加する
さらに、元データの分布から、有意水準5%や1%のエリアを示したいときもあるかと思います。そんなときは、geom_rect()
を使います。
そのためにまず有意水準1%の閾値を計算し、その結果をdf_data_thresholds
に代入します。(閾値の計算には、Rのデフォルト関数quantile()
を使用)
df_data %>%
group_by(Variable) %>%
summarise(
threshold_1 = quantile(sample, 0.01), #1%閾値
threshold_99 = quantile(sample, 0.99) #99%閾値
) -> df_data_thresholds
元データをgroup_by
したので、df_data_thresholds
にはfacet_grid()
で指定した要因と同じものが、すでに変数「Variable」として入っています。
あとはgeom_rect()
で、1%および99%の閾値をdf_data_thresholds
から指定すればOK。
df_data %>%
ggplot() +
geom_histogram(aes(x = sample)) + #ヒストグラム
geom_segment( #直線描画部分
data = df_real_data,
aes(x = sample, xend = sample, y = 0, yend = 200, colour = "orange")
) +
geom_rect( #領域描画部分(99%以上)
data = df_data_thresholds, #閾値の計算結果データを指定
aes(xmin = threshold_99, xmax = 8, ymin = 0, ymax = 200), #xminやxmaxは、元データから適当に設定
fill = "gray", alpha = 0.3
) +
geom_rect( #領域描画部分(1%以下)
data = df_data_thresholds, #閾値の計算結果データを指定
aes(xmin = -8, xmax = threshold_1, ymin = 0, ymax = 200), #xminやxmaxは、元データから適当に設定
fill = "gray", alpha = 0.3
) +
facet_grid(~ factor(Variable)) + #x,y,zのデータを別々のパネルに
theme_classic() + #自分好みの設定
theme( #自分好みの設定
strip.background = element_rect(linewidth = 0.5),
strip.placement = "outside",
panel.spacing = unit(1, "lines"),
legend.position = "none"
)
x軸やy軸のラベルはlabs()
で適宜変更すればOK。
これで以下のようなグラフが出力されます。
以上で完成です。