You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多分组配对t检验实现及箱线图显著性标记求助

在分面箱线图中添加分组t检验的显著性标记

我明白你现在的需求:针对分层结构(Group→Sub_group→Time points→State)的数据集,要在每个Sub_group和Time点组合下,对State的n和t做t检验,然后把显著性结果标注到已经画好的分面箱线图上。下面我一步步给你解决这个问题:

首先先确认你的数据生成代码(我帮你格式化并添加了随机种子保证结果可重复):

# 生成模拟数据
set.seed(123)
Var_measured<-sample(248)
State<-rep(c("t","n"), 124)
Time<-as.factor(sample(1:4, 62,replace = TRUE))
Sub_group<-sample(c("Met","Tet","Pep","Cep"),62, replace = TRUE)
Group<-sample(c("AA","Gly"),62, replace = TRUE)
df<-data.frame(Var_measured,State,Time,Sub_group,Group)

你已经完成的分面箱线图代码:

library(ggplot2)
p<-ggplot(df, aes(x= Time, y= Var_measured, fill= State))+ 
  geom_boxplot()+ 
  # coord_cartesian(ylim = c(0, 150000))+ 
  theme(axis.text.x=element_text(angle=90)) + 
  facet_grid(Group ~ Sub_group, scales = "free_y")
p

接下来我们分两步解决核心需求:计算每个分组下的t检验p值,然后把显著性标记添加到图上。


第一步:计算分组t检验的p值及标记位置

我们用dplyr按Group、Sub_group、Time分组,对每个组内的State(n和t)做t检验,同时计算标记需要的y轴位置(取该组内Var_measured的最大值加上偏移量,避免和箱线图重叠):

library(dplyr)

# 计算统计量
stat_results <- df %>%
  group_by(Group, Sub_group, Time) %>%
  summarise(
    # 做t检验(若方差不齐,可添加var.equal = FALSE切换为Welch检验)
    t_test_p = t.test(Var_measured ~ State)$p.value,
    # 计算标记的y轴位置:组内最大值 + 5(可根据实际数据调整偏移量)
    y_position = max(Var_measured) + 5,
    .groups = "drop"
  ) %>%
  # 根据p值生成标准化显著性标记
  mutate(
    sig_label = case_when(
      t_test_p < 0.001 ~ "***",
      t_test_p < 0.01 ~ "**",
      t_test_p < 0.05 ~ "*",
      TRUE ~ "ns"
    )
  )

第二步:在箱线图上添加显著性标记

这里提供两种常用方案,你可以根据需求选择:

方法1:用geom_text直接添加标记

把统计结果中的标记放到对应Time分组的中间位置,避免和箱线图重叠:

# 将Time转换为数值,方便计算中间位置
stat_results <- stat_results %>%
  mutate(x_position = as.numeric(Time))

p + 
  geom_text(data = stat_results, 
            aes(x = x_position, y = y_position, label = sig_label),
            inherit.aes = FALSE, # 避免继承原ggplot的映射关系
            size = 5, fontface = "bold")

方法2:用ggsignif包绘制显著性连线(更符合期刊图风格)

如果想要带连线的显著性标记,可以用ggsignif包的geom_signif:

library(ggsignif)

# 转换为geom_signif需要的数据格式
signif_data <- stat_results %>%
  mutate(
    # 为每个Time分组设置连线的左右边界
    xmin = as.numeric(Time) - 0.2,
    xmax = as.numeric(Time) + 0.2
  )

p +
  geom_signif(
    data = signif_data,
    aes(xmin = xmin, xmax = xmax, y_position = y_position, annotations = sig_label),
    inherit.aes = FALSE,
    tip_length = 0.01, # 调整连线尖端的长度
    textsize = 5
  )

额外提示

  1. 偏移量y_position = max(Var_measured) + 5可根据你的实际数据调整,若Var_measured数值较大,需增大偏移量保证标记不被箱线图遮挡。
  2. 若你的数据不符合t检验的正态性/方差齐性前提,可以把t.test替换为wilcox.test( Wilcoxon秩和检验)来做非参数检验。

内容的提问来源于stack exchange,提问作者MRF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:24:00