You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在ggplot2中为X轴下方添加分组信息标注?

在ggplot2中给X轴下方添加分组标注的两种实用方法

嘿,我来帮你搞定这个需求!在ggplot2里给X轴下方加分组标注,其实有几种好用的方法,我给你分享两种最常用的——一种是用专门的工具包省心省力,另一种是纯ggplot2手动实现,不用额外安装包。

先准备个示例数据集,方便我们演示:

library(ggplot2)
set.seed(123) # 固定随机数,结果可重复
df <- data.frame(
  sample = paste0("Sample_", 1:12), # 12个样本
  value = rnorm(12, 5, 1), # 随机数值
  group = rep(c("Group A", "Group B", "Group C"), each = 4) # 3个分组,每组4个样本
)

方法一:用ggh4x包一键实现(推荐)

ggh4x是ggplot2的拓展包,专门解决这类轴分组、多尺度的问题,用它来加分组标注超省心,不用手动算位置!

首先安装并加载包:

install.packages("ggh4x") # 第一次用需要安装
library(ggh4x)

然后直接在绘图代码里配置X轴的guide:

ggplot(df, aes(x = sample, y = value)) +
  geom_col(fill = "#2c3e50") + # 画柱状图
  scale_x_discrete(
    guide = axis_manual(
      breaks = df$sample, # X轴刻度是每个样本
      labels = df$sample, # 刻度标签
      group = df$group, # 指定分组依据
      group_labels = unique(df$group), # 分组的显示标签
      group_spacing = unit(10, "pt") # 分组之间的间距,可调整
    )
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) # 旋转X轴标签,避免重叠

这个方法的好处是:自动帮你把分组标注放在X轴下方,还会自动添加分组之间的间距,完全不用手动计算位置,适配各种样本数量的分组。


方法二:纯ggplot2手动实现(无需额外包)

如果你不想装新包,也可以用ggplot2自带的函数手动添加分组标注,核心是计算分组的中心位置,然后用annotate添加文本,再加分隔线。

第一步,先计算每个分组在X轴上的中心位置:

# 把样本转换成数值型,方便计算中心
group_centers <- aggregate(
  x = as.numeric(factor(df$sample)),
  by = list(df$group),
  FUN = mean
)
colnames(group_centers) <- c("group", "center") # 重命名列

然后绘图,添加标注和分隔线:

ggplot(df, aes(x = sample, y = value)) +
  geom_col(fill = "#2c3e50") +
  # 添加分组标注:放在X轴下方,Y轴位置设为负数
  annotate(
    "text",
    x = group_centers$center,
    y = -0.5,
    label = group_centers$group,
    fontface = "bold", # 加粗
    color = "#34495e"
  ) +
  # 添加分组分隔线:位置在分组之间的间隙
  annotate(
    "vline",
    xintercept = c(4.5, 8.5), # 这里因为每组4个样本,所以分隔在4.5和8.5的位置
    linetype = "dashed",
    color = "#95a5a6"
  ) +
  # 调整Y轴范围,确保标注不被截断,clip="off"允许元素超出绘图区域
  coord_cartesian(ylim = c(0, 7), clip = "off") +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    plot.margin = margin(b = 30, unit = "pt") # 增加底部边距,让标注完全显示
  )

这个方法需要你手动调整分隔线的位置和Y轴的边距,但好处是不用依赖额外包,适合环境受限的场景。


小技巧:美化分组标注

如果想让分组标注更美观,比如加个背景色,可以用ggtext包的element_markdown功能,把分组标签写成带HTML样式的文本,比如:

# 先安装ggtext
# install.packages("ggtext")
library(ggtext)

# 修改分组标签为带背景的样式
group_centers$group_label <- paste0(
  "<span style='background-color:#f0f3f5; padding:2px 8px; border-radius:4px;'>",
  group_centers$group,
  "</span>"
)

# 然后在annotate里用geom_richtext(来自ggtext)替换text
ggplot(df, aes(x = sample, y = value)) +
  geom_col(fill = "#2c3e50") +
  geom_richtext(
    data = group_centers,
    aes(x = center, y = -0.5, label = group_label),
    fill = NA, label.color = NA, # 去掉默认背景和边框
    size = 4
  ) +
  # 其余代码和之前一样
  annotate("vline", xintercept = c(4.5, 8.5), linetype = "dashed", color = "#95a5a6") +
  coord_cartesian(ylim = c(0, 7), clip = "off") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1), plot.margin = margin(b = 30, unit = "pt"))

这样就能得到带浅灰色背景的分组标注,看起来更醒目!

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

火山引擎 最新活动