缘由

统计是生信的基石之一

碎碎念

要爱一个具体的人,不要爱一个抽象的人; 要爱生活,不要爱生活的意义。 ——《卡拉马佐夫兄弟》

Ref

How to Add P-Values onto a Grouped GGPLOT using the GGPUBR R Package - Datanovia

解读

1. 基础分组比较与p值标注

数据准备与统计检验

library(ggpubr)
df <- ToothGrowth
df$dose <- as.factor(df$dose)
head(df, 3)
 
# 分组t检验与多重检验校正
stat.test <- df %>%
  group_by(dose) %>%
  t_test(len ~ supp) %>%
  adjust_pvalue(method = "bonferroni") %>%
  add_significance("p.adj")
stat.test

基础箱线图标注

bxp <- ggboxplot(
  df, x = "dose", y = "len", 
  color = "supp", palette = c("#00AFBB", "#E7B800")
)
 
# 添加p值标注
stat.test <- stat.test %>%
  add_xy_position(x = "dose", dodge = 0.8)
bxp + stat_pvalue_manual(
  stat.test, label = "p", tip.length = 0
)

2. p值标注的多种样式定制

调整标签位置与显示空间

# 为p值标签预留10%的顶部空间
bxp + stat_pvalue_manual(
  stat.test, label = "p", tip.length = 0
) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.1)))

多种标签格式选择

# 显示校正后p值,移除括号
bxp + stat_pvalue_manual(
  stat.test, label = "p.adj", tip.length = 0,
  remove.bracket = TRUE
)
 
# 组合显示校正p值和显著性星号,隐藏不显著结果
bxp + stat_pvalue_manual(
  stat.test, label = "{p.adj}{p.adj.signif}", 
  tip.length = 0, hide.ns = TRUE
)

3. 条形图中的p值标注技巧

基础条形图标注

bp <- ggbarplot(
  df, x = "dose", y = "len", add = "mean_sd", 
  color = "supp", palette = c("#00AFBB", "#E7B800"),
  position = position_dodge(0.8)
)
 
# 基于均值+标准差计算标注位置
stat.test <- stat.test %>%
  add_xy_position(fun = "mean_sd", x = "dose", dodge = 0.8) 
bp + stat_pvalue_manual(
  stat.test, label = "p.adj.signif", tip.length = 0.01
)

调整标注位置

# 向下移动括号
bp + stat_pvalue_manual(
  stat.test, label = "p.adj.signif", tip.length = 0,
  bracket.nudge.y = -2  # 垂直调整位置
)

4. 堆积条形图的特殊处理

手动指定位置

bp2 <- ggbarplot(
  df, x = "dose", y = "len", add = "mean_sd", 
  color = "supp", palette = c("#00AFBB", "#E7B800"),
  position = position_stack()  # 堆积条形图
)
 
# 手动指定y轴位置
bp2 + stat_pvalue_manual(
  stat.test, label = "p.adj.signif", tip.length = 0.01,
  x = "dose", y.position = c(30, 45, 60)
)

自动计算位置

# 自动计算堆积图的位置
stat.test <- stat.test %>%
  add_xy_position(fun = "mean_sd", x = "dose", stack = TRUE) 
bp2 + stat_pvalue_manual(
  stat.test, label = "p.adj.signif", 
  remove.bracket = TRUE, vjust = -0.2  # 垂直调整标签
)

5. 复杂分组结构的标注策略

按组分步标注

pwc <- df %>%
  group_by(supp) %>%
  t_test(len ~ dose, p.adjust.method = "bonferroni")
 
# 按supp分组显示p值
pwc <- pwc %>% add_xy_position(x = "dose")
bxp +
  stat_pvalue_manual(
    pwc, color = "supp", step.group.by = "supp",  # 按组分步
    tip.length = 0, step.increase = 0.1
  )

精确分组定位

# 考虑分组变量调整x位置
pwc <- pwc %>% add_xy_position(x = "dose", group = "supp")
bxp +
  stat_pvalue_manual(
    pwc, color = "supp", step.group.by = "supp",
    tip.length = 0, step.increase = 0.1
  )

6. 选择性显示统计结果

过滤特定分组结果

# 只显示VC组的结果
pwc.filtered <- pwc %>% 
  add_xy_position(x = "dose", fun = "mean_sd", dodge = 0.8) %>%
  filter(supp == "VC")
bp +
  stat_pvalue_manual(
    pwc.filtered, color = "supp", step.group.by = "supp",
    tip.length = 0, step.increase = 0
  )