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

如何为含百分比/逻辑数据的条形图添加显著性标注线

解决分组条形图添加显著性标注的问题

问题背景

你基于iris数据集生成了长格式数据,展示不同物种下各逻辑变量的TRUE值占比,并绘制了分组条形图,但无法用ggpubr给每组条形添加显著性标注(期望效果为同测量指标下不同物种间的对比线与显著性符号)。核心问题是你使用了汇总后的长格式数据,而统计检验需要原始的二分类样本数据。

解决方案

步骤1:保留原始二分类数据

先创建包含原始逻辑变量的宽格式数据,用于后续统计检验:

library(tidyverse)

# 生成带原始逻辑变量的数据集
iris_logical <- iris %>%
  mutate(
    Long.Sepal.Length = Sepal.Length > 6,
    Long.Sepal.Width = Sepal.Width > 3,
    Long.Petal.Length = Petal.Length > 2.5,
    Long.Petal.Width = Petal.Width > 0.3
  )

# 转成长格式,适配绘图与检验的统一结构
iris_logical_long <- iris_logical %>%
  pivot_longer(
    cols = starts_with("Long"),
    names_to = "Measurement",
    values_to = "Is_Long"
  )

方案一:用ggsignif直接添加标注

ggsignif可以直接在ggplot图层中调用原始数据计算检验并添加标注:

library(ggsignif)

ggplot(long_data, aes(x = Measurement, y = Percentage_True, fill = Species)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.8)) +
  labs(
    x = "测量指标",
    y = "TRUE占比(%)",
    fill = "物种"
  ) +
  # 添加同测量指标下物种间的显著性对比
  geom_signif(
    data = iris_logical_long,
    aes(x = Measurement, group = Species, y = Is_Long),
    # 指定需要比较的物种组合
    comparisons = list(c("setosa", "versicolor"), c("setosa", "virginica"), c("versicolor", "virginica")),
    # 二分类数据用Fisher精确检验
    test = "fisher.test",
    # 显示显著性符号(* ** *** ns)
    map_signif_level = TRUE,
    position = position_dodge(width = 0.8),
    # 设置标注的y轴位置,避免重叠
    y_position = rep(c(105, 115, 125), 4),
    tip.length = 0.01
  ) +
  # 扩展y轴范围,容纳标注
  ylim(0, 130)

方案二:用ggpubr预计算检验结果再添加标注

先手动计算所有两两比较的p值,再用stat_pvalue_manual添加标注:

library(ggpubr)

# 循环计算每个测量指标下物种间的Fisher检验结果
test_results <- map_dfr(names(iris_logical)[5:8], function(var) {
  compare_means(
    formula = as.formula(paste(var, "~ Species")),
    data = iris_logical,
    method = "fisher.test",
    p.adjust.method = "bonferroni" # 多重检验校正
  ) %>%
    mutate(Measurement = var)
})

# 整理检验结果,适配标注格式
test_results <- test_results %>%
  mutate(
    # 设置每个对比的y轴位置
    y.position = case_when(
      group1 == "setosa" & group2 == "versicolor" ~ 105,
      group1 == "setosa" & group2 == "virginica" ~ 115,
      group1 == "versicolor" & group2 == "virginica" ~ 125
    ),
    # 转换p值为显著性符号
    p.signif = case_when(
      p.adj < 0.001 ~ "***",
      p.adj < 0.01 ~ "**",
      p.adj < 0.05 ~ "*",
      TRUE ~ "ns"
    )
  )

# 绘图并添加标注
ggbarplot(
  long_data,
  x = "Measurement",
  y = "Percentage_True",
  fill = "Species",
  position = position_dodge(width = 0.8),
  xlab = "测量指标",
  ylab = "TRUE占比(%)",
  legend.title = "物种"
) +
  stat_pvalue_manual(
    test_results,
    x = "Measurement",
    y.position = "y.position",
    label = "p.signif",
    position = position_dodge(width = 0.8),
    tip.length = 0.01
  ) +
  ylim(0, 130)

关键说明

  • 统计检验必须基于原始样本的二分类数据,而非汇总后的百分比数据,这是你之前用ggpubr失败的核心原因。
  • 两种方案都需要将原始逻辑数据与绘图的长格式数据对应,确保测量指标(Measurement)的分组一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 10:37:03