如何在R的分组ggplot图上添加配对t检验的p值
针对分组配对t检验并添加p值到箱线图的实现方案
示例数据
| fish_ID | color | inst | time |
|---|---|---|---|
| 1 | blue | inst_0 | 136 |
| 1 | green | inst_0 | 40 |
| 1 | red | inst_0 | 111 |
| 1 | yellow | inst_0 | 20 |
| 1 | blue | inst_3 | 112 |
| 1 | green | inst_3 | 13 |
| 1 | red | inst_3 | 15 |
| 1 | yellow | inst_3 | 90 |
| 2 | blue | inst_0 | 110 |
| 2 | green | inst_0 | 80 |
| 2 | red | inst_0 | 11 |
| 2 | yellow | inst_0 | 34 |
| 2 | blue | inst_3 | 19 |
| 2 | green | inst_3 | 130 |
| 2 | red | inst_3 | 15 |
| 2 | yellow | inst_3 | 88 |
问题背景
我拥有大量上述格式的fish_ID数据,需要针对每种颜色组,对inst_0和inst_3的time均值做配对t检验。已用以下代码绘制分组箱线图:
library(ggplot2) library(ggprism) ggplot(mydata , aes(x = factor(inst), y = time, fill = color)) + geom_boxplot(position = position_dodge(width = 0.75)) + scale_fill_manual(values = c("blue" = "blue", "green" = "green", "red" = "red", "yellow" = "yellow")) + theme_prism()
现在需要将各颜色组的配对t检验p值添加到图中,不清楚如何针对每个颜色组完成inst_0与inst_3的两两比较。
实现方案
步骤1:计算各颜色组的配对t检验p值
先将数据转换为宽格式,确保同一fish_ID+color组合下同时存在inst_0和inst_3的观测,再按颜色分组执行配对t检验:
library(dplyr) library(tidyr) # 转换为宽格式,保留配对数据 wide_data <- mydata %>% pivot_wider(names_from = inst, values_from = time) %>% na.omit() # 移除缺失配对的样本 # 按颜色分组计算配对t检验p值,并格式化标签 p_values <- wide_data %>% group_by(color) %>% summarize( p_val = t.test(inst_0, inst_3, paired = TRUE)$p.value, # 生成可读性强的p值标签,支持星号或数值显示 p_label = case_when( p_val < 0.001 ~ "***", p_val < 0.01 ~ "**", p_val < 0.05 ~ "*", TRUE ~ "ns" # 若需要显示具体数值,替换为:sprintf("p = %.3f", p_val) ) )
步骤2:将p值添加到箱线图中
推荐使用ggsignif包手动指定比较位置,或用ggpubr包自动适配分组布局:
方法1:用ggsignif手动控制标记位置
install.packages("ggsignif") library(ggsignif) # 定义每个颜色组的配对比较位置(适配position_dodge(width=0.75)的布局) color_x_pos <- c(blue = 0.8, green = 0.95, red = 1.1, yellow = 1.25) y_offset <- max(mydata$time) + c(10, 15, 20, 25) # 避免标记与箱线图重叠 ggplot(mydata, aes(x = factor(inst), y = time, fill = color)) + geom_boxplot(position = position_dodge(width = 0.75)) + scale_fill_manual(values = c("blue" = "blue", "green" = "green", "red" = "red", "yellow" = "yellow")) + theme_prism() + # 添加配对t检验p值标记 geom_signif( data = p_values, aes( xmin = color_x_pos, xmax = color_x_pos + 1, annotations = p_label, y_position = y_offset ), manual = TRUE, tip_length = 0.01, textsize = 4 )
方法2:用ggpubr自动适配分组
install.packages("ggpubr") library(ggpubr) ggplot(mydata, aes(x = factor(inst), y = time, fill = color)) + geom_boxplot(position = position_dodge(width = 0.75)) + scale_fill_manual(values = c("blue" = "blue", "green" = "green", "red" = "red", "yellow" = "yellow")) + theme_prism() + stat_compare_means( aes(group = color), method = "t.test", paired = TRUE, label = "p.signif", # 显示星号,若要数值用"p.format" position = position_dodge(width = 0.75), hide.ns = TRUE # 可选:隐藏无显著性的标记 )
注意事项
- 确保数据为配对设计:每个
fish_ID在同一color下同时有inst_0和inst_3的观测,否则配对t检验不适用。 - 可根据图的高度调整
y_offset参数,避免p值标记与箱线图或异常值重叠。 - 若需要校正多重比较,可在计算p值时添加
p.adjust()函数,比如p_val = p.adjust(t.test(inst_0, inst_3, paired = TRUE)$p.value, method = "bonferroni")。
内容的提问来源于stack exchange,提问作者Balina
相关产品推荐
相关产品推荐

