背景
論文を読んでいて、以下のような図を見つけました。Split-violinというみたいです。
(引用:Lu, X., & Yang, J. (2025). Second language embodiment of action verbs: the impact of bilingual experience as a multidimensional spectrum. Bilingualism: Language and Cognition, 1-17.)
通常、このような2変数の描画場合だと、4つのバイオリンプロットを描画するため、スペースを取ってしまいます。
mtcars$vs <- factor(mtcars$vs)
mtcars$am <- factor(mtcars$am)
colors <- c("1" = "#f79428", "0" = "#5383c3")
ggplot(mtcars, aes(x = am, y = mpg, group = interaction(am, vs), fill = vs)) +
geom_violin(alpha = 0.5, position = position_dodge(width = 0.9), trim = F) +
geom_jitter(aes(color = vs), position = position_dodge(width = 0.9), alpha = 0.8) +
scale_fill_manual(values = colors) +
scale_color_manual(values = colors)
Split-violinでは上述のように、2つのバイオリンプロットを半分ずつくっつけて描画するためスペースを節約できます。また、データの比較も行いやすい気がします。
実装
この図専用のRの関数が存在します。2025年3月現在、いまだCRANには登録されていないようです(パッケージのGithubレポジトリ:introdataviz)。CRANに登録がないので、devtools()
関数で開発版をダウンロードします(私のRのバージョンは、4.3.2で、Windowsを使用しています)。
library(devtools)
install_github("psyteachr/introdataviz")
データセットは、mtcars
を使用しました。描画に使用するデータは因子型に変換しておきます。
mtcars$am <- factor(mtcars$am)
mtcars$vs <- factor(mtcars$vs)
Step 1
分かりやすいように細かい設定は取り払っています。geom_split_violin()
の中には、trim = F
を加えたほうが滑らかな描画になります。また、color = NA
を追加することで枠線が消えます。
- コード
library(ggplot2)
ggplot(mtcars, aes(x = am, y = mpg, fill = vs)) +
introdataviz::geom_split_violin(trim = F, color = NA) +
labs(x = "am", y = "mpg")
Step 2
各データを点で、平均値とエラーバーも図に追加しました。geom_split_violin()
の中のalpha
で図の透明度を薄くしないと、各データの点が塗りつぶされて見えません。
- コード
ggplot(mtcars, aes(x = am, y = mpg, fill = vs)) +
introdataviz::geom_split_violin(alpha = 0.3, trim = F, color = NA) +
# 点を描画するコード
geom_jitter(aes(color = vs), position = position_dodge(.5), alpha = 0.8) +
# 平均値とエラーバーを描画するコード
stat_summary(fun.data = "mean_se", geom = "pointrange", show.legend = F,
position = position_dodge(.175)) +
labs(x = "am", y = "mpg")
Step 2(ボックスプロット)
ボックスプロットを描画することもできます。
- コード
ggplot(mtcars, aes(x = am, y = mpg, fill = vs)) +
introdataviz::geom_split_violin(, alpha = 0.3, trim = F, color = NA) +
geom_jitter(aes(color = vs), position = position_dodge(.5), alpha = 0.8) +
#ボックスプロットを追加
geom_boxplot(width = .2, alpha = .6, show.legend = FALSE) +
labs(x = "am", y = "mpg")
Step 3
上で紹介した論文内の図に近い色を設定してみます。1とコーディングしているデータにオレンジ、0に青を指定します。目視で色を選んでいるので、全く同じ色ではありません。
- コード
colors <- c("1" = "#f79428", "0" = "#5383c3")
alpha
を0.3から0.5に変更し、図の色を少し濃ゆくしています。また、theme_classic()
を追加し、図の枠線をL字型に変更しています。
ggplot(mtcars, aes(x = am, y = mpg, fill = vs)) +
introdataviz::geom_split_violin(, alpha = 0.5, trim = F, color = NA) +
geom_jitter(aes(color = vs), position = position_dodge(.5), alpha = 0.8) + # データ点散布
stat_summary(fun.data = "mean_se", geom = "pointrange", show.legend = F,
position = position_dodge(.175)) +
#上で指定した色を設定
scale_fill_manual(values = colors) +
scale_color_manual(values = colors) +
#図の枠線をL字型に設定
theme_classic()
labs(x = "am", y = "mpg")
完成版
上で紹介した図には有意差を表すアスタリスクも描画されています。ggpubr
パッケージのstat_compare_means
関数を用いて有意差がある条件間にはアスタリスクを描画するように設定します。他にも有意差を表示させる方法があるようです(参考記事:https://indenkun.hatenablog.com/entry/2020/08/13/233029)。今回は、同じam条件内でvs0とvs1の平均値差を検定しています。
- コード
library(ggpubr)
ggplot(mtcars, aes(x = am, y = mpg, fill = vs)) +
introdataviz::geom_split_violin(alpha = 0.5, trim = FALSE, color = NA) +
geom_jitter(aes(color = vs), position = position_dodge(0.5), alpha = 0.8) +
stat_summary(fun.data = "mean_se", geom = "pointrange", show.legend = FALSE,
position = position_dodge(0.175)) +
# グループ間の統計的有意差を表示
stat_compare_means(aes(group = vs), method = "t.test", label = "p.signif") +
scale_fill_manual(values = colors) +
scale_color_manual(values = colors) +
theme_classic() +
labs(x = "am", y = "mpg")
最後に
この図を再現してほしい!というものがあればご連絡お願いします。