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

如何在cowplot中为多幅ggplot2图表添加共用顶部X轴

实现共用顶部X轴的方案

要给纵向排列的多幅图表添加共用顶部X轴,我们可以通过以下步骤实现:

  1. 修改单个图表:隐藏每个图表的顶部轴元素,并统一X轴范围以确保对齐。
  2. 创建独立的顶部轴图表:仅保留顶部X轴,移除其他无关元素。
  3. 组合所有图表:将顶部轴图表与其他图表纵向排列,调整高度比例并对齐。

完整修改后的代码

library(ggplot2)
library(cowplot)
library(ggtext)
library(dplyr)

mylist <- list()
mylist[["ID1"]][["sequence"]] <- "AGAATATTATACATTCATCT"
mylist[["ID2"]][["sequence"]] <- "GCTAGCGTTTAGTTTAGCTG"
mylist[["ID3"]][["sequence"]] <- "AACCCTTTAAACTCGAAGTA"
set.seed(123)
mylist[["ID1"]][["data"]] <- data.frame(time=1:100, value=rnorm(100, mean=10, sd=2))
mylist[["ID2"]][["data"]] <- data.frame(time=1:100, value=rnorm(100, mean=2, sd=1))
mylist[["ID3"]][["data"]] <- data.frame(time=1:100, value=rnorm(100, mean=5, sd=3))
indexes <- seq(5, 100, length.out=20)
all_df <- NULL

# 生成单个图表,隐藏顶部轴元素
for (id in names(mylist)){
  seqsplit <- unlist(strsplit(mylist[[id]][["sequence"]], ""))
  ind_df <- data.frame(call=seqsplit, time=indexes)
  final_df <- dplyr::left_join(mylist[[id]][["data"]], ind_df, by="time")
  xcolors <- ifelse(seqsplit=="A", "green", ifelse(seqsplit=="C", "blue", ifelse(seqsplit=="G", "black", "red")))
  
  P <- ggplot2::ggplot(final_df, ggplot2::aes(x=time, y=value)) +
    ggplot2::geom_line(linewidth=0.5) +
    ggplot2::scale_x_continuous(
      breaks=indexes, 
      labels=seqsplit, 
      expand=c(0,1), 
      limits=c(0, 101) # 统一X轴范围
    ) +
    ggplot2::scale_y_continuous(breaks=seq(-5, 15, 5), limits=c(-5,15)) +
    ggplot2::theme_light() +
    ggplot2::theme(
      axis.title=ggplot2::element_blank(),
      axis.text.x=ggtext::element_markdown(face="bold", color=xcolors),
      axis.text.top=ggplot2::element_blank(), # 隐藏顶部轴文本
      axis.ticks.top=ggplot2::element_blank(), # 隐藏顶部轴刻度
      axis.line.top=ggplot2::element_blank(), # 隐藏顶部轴线
      plot.margin=ggplot2::margin(t=0, r=5, b=5, l=5) # 移除顶部边距,避免间隙
    )
  mylist[[id]][["plot"]] <- P
}

# 创建共用顶部X轴图表(刻度为序列位置1-20,若要显示indexes值可替换labels为indexes)
top_axis_plot <- ggplot() +
  scale_x_continuous(
    breaks=indexes,
    labels=1:20, # 替换为indexes可显示原始时间刻度
    expand=c(0,1),
    limits=c(0,101),
    position="top" # 将轴放在顶部
  ) +
  theme_light() +
  theme(
    axis.title=element_blank(),
    axis.text.y=element_blank(), # 隐藏Y轴文本
    axis.ticks.y=element_blank(), # 隐藏Y轴刻度
    axis.line.y=element_blank(), # 隐藏Y轴线
    panel.grid=element_blank(), # 隐藏网格线
    panel.border=element_blank(), # 隐藏面板边框
    plot.margin=margin(b=0, r=5, t=5, l=5) # 移除底部边距,避免间隙
  )

# 组合所有图表
plot_list <- sapply(mylist, "[", "plot")
plot_list_with_top <- c(list(top_axis_plot), plot_list)

grDevices::pdf(file="test.pdf", height=6, width=10) # 调整高度以容纳顶部轴
print(
  cowplot::plot_grid(
    plotlist=plot_list_with_top,
    ncol=1,
    align="v", # 垂直对齐
    rel_heights=c(0.1, rep(1, length(plot_list))) # 顶部轴占比更小
  )
)
grDevices::dev.off()

关键调整说明

  • 统一X轴范围:所有图表(包括顶部轴)设置相同的limits=c(0,101),确保轴的对齐精度。
  • 隐藏冗余元素:单个图表移除顶部轴的文本、刻度和线;顶部轴图表移除Y轴所有元素和网格线,仅保留顶部X轴。
  • 调整边距:通过plot.margin移除顶部轴与第一个图表之间的间隙,提升布局紧凑性。
  • 高度比例:使用rel_heights让顶部轴占据较小的垂直空间,避免挤压主图表。

如果需要顶部轴显示原始indexes数值,只需将top_axis_plot中的labels=1:20替换为labels=indexes即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 17:55:58