如何用ggplot2+ggforce创建两个不同区域的放大插入子图并并排展示?
实现双放大子图的解决方案
ggforce::facet_zoom仅支持单个放大面板,要添加第二个放大子图并将其放在第一个的右侧,推荐使用patchwork包来组合多个ggplot图形,实现灵活的布局控制。
完整代码示例
library(ggplot2) library(ggforce) library(patchwork) # 绘制主图,添加放大区域标记 p_main <- ggplot(mtcars, aes(x = mpg, y = disp, color = factor(cyl), shape = factor(carb))) + geom_point(size = 2) + # 用虚线框标记两个放大区域 annotate("rect", xmin = 15, xmax = 20, ymin = 200, ymax = 300, fill = NA, color = "#E63946", linewidth = 1, linetype = "dashed") + annotate("rect", xmin = 30, xmax = 35, ymin = 0, ymax = 100, fill = NA, color = "#457B9D", linewidth = 1, linetype = "dashed") + labs(x = "Miles/(US) gallon", y = "Displacement (cu.in.)", color = "Cylinders", shape = "Carburetors") # 第一个放大子图:限定坐标范围,保留所有数据的视觉映射 p_zoom1 <- ggplot(mtcars, aes(x = mpg, y = disp, color = factor(cyl), shape = factor(carb))) + geom_point(size = 2) + coord_cartesian(xlim = c(15, 20), ylim = c(200, 300)) + labs(title = "Zoom: 15-20 mpg | 200-300 disp") + theme(plot.title = element_text(size = 10), axis.title = element_text(size = 9)) # 第二个放大子图 p_zoom2 <- ggplot(mtcars, aes(x = mpg, y = disp, color = factor(cyl), shape = factor(carb))) + geom_point(size = 2) + coord_cartesian(xlim = c(30, 35), ylim = c(0, 100)) + labs(title = "Zoom: 30-35 mpg | 0-100 disp") + theme(plot.title = element_text(size = 10), axis.title = element_text(size = 9)) # 组合布局:主图占上方整行,两个放大子图并排占下方一行 p_main / (p_zoom1 + p_zoom2) + plot_layout(heights = c(3, 1)) + # 调整主图与子图的高度比例 plot_annotation(title = "mtcars Scatter Plot with Dual Zoom Panels")
关键说明
- 替代facet_zoom:由于
facet_zoom仅支持单个放大面板,改用patchwork组合独立的ggplot对象,实现多面板布局 - coord_cartesian的优势:使用
coord_cartesian()而非xlim()/ylim(),避免过滤数据,仅放大指定区域,保持与主图一致的视觉比例和数据映射 - 布局控制:通过
patchwork的语法/实现上下布局,+实现左右布局,plot_layout()可调整各区域的尺寸比例 - 视觉标记:主图中添加的虚线框可帮助用户快速对应放大区域与子图
如果需要将放大子图作为内嵌插入图放在主图内部右侧,可使用annotation_custom()将子图转换为grob对象后嵌入,示例代码如下:
library(grid) # 将子图转换为grob对象 g_zoom1 <- ggplotGrob(p_zoom1) g_zoom2 <- ggplotGrob(p_zoom2) # 主图内嵌双放大子图 p_main + annotation_custom(grob = g_zoom1, xmin = 25, xmax = 35, ymin = 220, ymax = 350) + annotation_custom(grob = g_zoom2, xmin = 25, xmax = 35, ymin = 0, ymax = 130)
这种方式需要手动调整xmin/xmax/ymin/ymax参数来定位插入图的位置。
内容的提问来源于stack exchange,提问作者Daniel Valencia C.
相关产品推荐
相关产品推荐

