如何在cowplot中为多幅ggplot2图表添加共用顶部X轴
实现共用顶部X轴的方案
要给纵向排列的多幅图表添加共用顶部X轴,我们可以通过以下步骤实现:
- 修改单个图表:隐藏每个图表的顶部轴元素,并统一X轴范围以确保对齐。
- 创建独立的顶部轴图表:仅保留顶部X轴,移除其他无关元素。
- 组合所有图表:将顶部轴图表与其他图表纵向排列,调整高度比例并对齐。
完整修改后的代码
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
相关产品推荐
相关产品推荐

