R语言地质剖面图:跨多图连接线条与图表对齐需求
实现跨图连线与对齐的地质剖面图
针对你用ggplot2+gridExtra绘制地质剖面图后,需要跨图连接相似地质区域并对齐图表的需求,我整理了两种实用的实现方案,核心是先保证y轴深度对齐,再用底层绘图工具添加跨图线条:
第一步:统一y轴范围,确保图表对齐
首先必须让两个子图的深度轴(y轴)范围完全一致,这样地质区域的位置才能精准对齐。我们在scale_y_continuous里显式指定limits,同时调整图的边距,给跨图连线留出空间:
library(ggplot2) library(cowplot) # 用于拼接和绘制跨图元素 library(grid) # 固定随机种子,保证示例可重现 set.seed(123) df1 = data.frame(replicate(2,sample(0:200,100,rep=TRUE))) df1$depth = seq.int(nrow(df1)) df2 = data.frame(replicate(2,sample(0:200,100,rep=TRUE))) df2$depth = seq.int(nrow(df1)) top1 = 32 top2 = 50 # 绘制第一个子图,固定y轴范围并调整边距 plot1 = ggplot(df1, aes(y = depth, x = X1))+ scale_y_continuous(trans = "reverse", limits = c(100, 1))+ # 强制y轴范围一致 geom_path()+ geom_hline(yintercept=top1, colour = "red")+ annotate(geom="text", x=25, y=top1, label=top1, color="red")+ theme_bw()+ theme(panel.grid.major = element_line(colour = "grey"), panel.background = element_rect(colour = "black", size=0.5), plot.margin = margin(5, 0, 5, 5))+ # 右侧留空给连线 ylab("Depth ft")+ ggtitle("plot1") # 绘制第二个子图,和第一个保持完全相同的y轴范围 plot2 = ggplot(df2, aes(y = depth, x = X1))+ scale_y_continuous(trans = "reverse", limits = c(100, 1))+ geom_path()+ geom_hline(yintercept=top2, colour = "red")+ annotate(geom="text", x=25, y=top2, label=top2, color="red")+ theme_bw()+ theme(panel.grid.major = element_line(colour = "grey"), panel.background = element_rect(colour = "black", size=0.5), plot.margin = margin(5, 5, 5, 0))+ # 左侧留空给连线 ylab("Depth ft")+ ggtitle("plot2")
方案一:用cowplot快速添加跨图连线
cowplot的ggdraw和plot_grid组合非常适合这类需求,先拼接对齐的子图,再用相对坐标绘制连线:
# 垂直对齐拼接两个图 combined_plot = plot_grid(plot1, plot2, ncol = 2, align = "v") # 绘制跨图连线:这里把depth值转换成画布的相对坐标(0=底部,1=顶部) ggdraw(combined_plot) + draw_line(x = c(0.5, 0.5), # x坐标是画布中间位置,对应两个图的分界处 y = c((100 - top1)/100, (100 - top2)/100), # 转换为相对y坐标 color = "blue", size = 1.2)
方案二:用patchwork+grid精细控制连线
如果你更偏好patchwork,可以通过ggplotGrob获取图的布局信息,精准定位面板位置后绘制连线:
library(patchwork) # 拼接图并获取底层布局对象 p = plot1 + plot2 + plot_layout(ncol = 2) gt = ggplotGrob(p) # 绘制拼接图,再添加跨面板连线 grid.newpage() grid.draw(gt) # 获取两个面板的位置信息(单位是网格列/行) panel1 = gt$layout[gt$layout$name == "panel-1-1", c("t", "l", "b", "r")] panel2 = gt$layout[gt$layout$name == "panel-2-1", c("t", "l", "b", "r")] # 计算depth值对应的面板相对y坐标(npc单位,0=底部,1=顶部) y_pos1 = (100 - top1)/99 # 因为depth范围是1-100,共99个间隔 y_pos2 = (100 - top2)/99 # 绘制跨面板的连线 grid.lines( x = c(panel1$r, panel2$l) / gt$widths, # 转换为画布相对x坐标 y = c(y_pos1, y_pos2), gp = gpar(col = "blue", lwd = 2, lty = 2) # 可以自定义线条样式 )
关键注意事项
- 对齐前提:一定要保证两个子图的y轴范围完全一致,否则连线肯定会错位;
- 边距调整:通过
plot.margin调整子图的边距,避免连线被图的边框或坐标轴遮挡; - 坐标转换:跨图连线需要将实际的depth值转换为画布/面板的相对坐标(0到1的范围),这样才能精准定位。
内容的提问来源于stack exchange,提问作者berwyn72
相关产品推荐
相关产品推荐

