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

如何在R中创建带多层X轴的条形图?附数据与代码求助

在ggplot2中创建多层X轴的解决方案

我明白你想要在ggplot2里实现带有两层X轴(比如上层显示Site,下层显示Time)的条形图,这在ggplot里没有原生的直接支持,但我们可以通过两种常用方法来实现,下面结合你的示例数据详细说明:

首先准备可复现的示例数据

先把你提供的示例数据整理成可用的数据框:

df <- data.frame(
  Site = c("CAV1", "CAV1", "CAV2", "CAV2"),
  Time = c("DAY0", "Day1", "DAY0", "Day1"),
  Abundance = c(7.15e-06, 3.39e-06, 7.15e-07, 3.39e-07),
  Group = c("X", "X", "Y", "Y"),
  STDEV = c(1.968384e-06, 4.934761e-07, 8.636959e-07, 3.511951e-07)
)

方法1:用分面(Facet)模拟多层X轴(推荐)

这是最符合ggplot设计理念的方式,通过按Site分面,让每个分面下显示对应Time的条形,视觉上就形成了"上层Site,下层Time"的多层轴效果:

library(ggplot2)

ggplot(df, aes(x = Time, y = Abundance, fill = Site)) +
  # 用geom_col替代geom_bar(stat="identity"),更直观
  geom_col(color = "black", position = position_dodge(width = 0.8)) +
  # 添加误差棒(利用你的STDEV数据)
  geom_errorbar(aes(ymin = Abundance - STDEV, ymax = Abundance + STDEV),
                position = position_dodge(width = 0.8), width = 0.2) +
  # 按Site分面,每行显示所有分面,X轴仅保留当前分面的Time
  facet_wrap(~Site, scales = "free_x", nrow = 1) +
  theme_minimal() +
  # 自定义主题,让分面标签更醒目,去掉分面间空隙
  theme(strip.text = element_text(size = 12, face = "bold"),
        panel.spacing = unit(0, "lines"),
        axis.title.x = element_blank())

这种方法的优势是:不需要手动调整坐标,当你有大量Site时会自动适配,维护起来非常方便。


方法2:手动添加上层X轴(自定义外观)

如果你需要更紧凑的单轴视觉效果,可以手动构建上层轴标签和线条,适合对外观有严格要求的场景:

# 先创建组合因子,确保Time的顺序按Site分组
df$Time_Site <- factor(paste(df$Site, df$Time, sep = "_"),
                       levels = paste(rep(c("CAV1", "CAV2"), each = 2), c("DAY0", "Day1"), sep = "_"))

ggplot(df, aes(x = Time_Site, y = Abundance, fill = Site)) +
  geom_col(color = "black", position = position_dodge(width = 0.8)) +
  geom_errorbar(aes(ymin = Abundance - STDEV, ymax = Abundance + STDEV),
                position = position_dodge(width = 0.8), width = 0.2) +
  theme_minimal() +
  # 下层X轴仅显示Time标签
  scale_x_discrete(labels = gsub(".*_", "", levels(df$Time_Site))) +
  # 添加上层Site标签
  annotate("text", x = c(1.5, 3.5), y = -0.5e-06, label = c("CAV1", "CAV2"),
           size = 4, fontface = "bold") +
  # 添加上层轴的分隔线
  annotate("segment", x = c(0.5, 2.5), xend = c(2.5, 4.5), y = -0.4e-06, yend = -0.4e-06) +
  # 调整Y轴范围,避免上层标签被截断
  ylim(-1e-06, max(df$Abundance + df$STDEV)) +
  # 调整X轴文本的边距,留出上层轴空间
  theme(axis.title.x = element_blank(),
        axis.text.x = element_text(margin = margin(t = 10)))

注意:这种方法需要手动调整坐标位置(比如y的取值),当Site数量变化时需要重新计算标签位置,灵活性稍差。

你可以根据自己的需求选择其中一种方法,两种都能基于你原来的代码快速修改实现~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 07:57:39