R plotly子图同时共享X轴Y轴实现带分组标注的交互式散点图
可交互分组标注散点图实现方案
核心思路
之前两次单独调用subplot无法同时共享双轴的核心原因是没有做嵌套拼接,正确的拼接逻辑如下:
- 先统一所有子图的X、Y轴范围,避免自动缩放导致错位
- 纵向拼接顶部X轴标注条 + 主体散点图,开启X轴共享
- 把上一步得到的整体图,和右侧Y轴标注条横向拼接,开启Y轴共享
修正后完整可运行代码
library(ggplot2) library(plotly) # 固定随机种子保证结果可复现 set.seed(123) x <- sample(1:1000, 10, replace=FALSE) y <- sample(1001:2000, 10, replace=FALSE) # 主散点图数据 df <- data.frame(pos1 = c(x[1:5], y[1:5]), pos2 =c(x[6:10], y[6:10]), Sample = c(rep("Sample1", 5), rep("Sample2", 5))) # 标注条数据,修正Sample名称大小写保证分组统一 df2 <- data.frame(Sample = c("Sample1", "Sample2"), pos1 = c(1,1001), pos2 = c(1000,2000)) df2$x_median <- (df2$pos1 + df2$pos2)/2 # 统一轴范围,避免自动缩放错位 x_range <- range(c(df$pos1, df2$pos1, df2$pos2)) y_range <- range(c(df$pos2, df2$pos1, df2$pos2)) # 主体散点图 p <- ggplot(df, aes(x=pos1, y=pos2, fill = Sample)) + geom_point(size = 2) + theme_bw() + xlim(x_range) + ylim(y_range) + theme(legend.title = element_blank(), legend.position = "bottom") # 顶部X轴分组标注条 ann_x <- ggplot(data = df2) + geom_rect(aes(xmin = pos1, xmax = pos2, ymin = 0, ymax = 0.4, fill = Sample), color = "black", size = 0.3, alpha = 0.2) + geom_text(aes(x = x_median, y = .2, label = Sample), vjust = .8, fontface = "bold", color = "black") + xlim(x_range) + theme_void() + theme(legend.position = "none") # 右侧Y轴分组标注条 ann_y <- ggplot(data = df2) + geom_rect(aes(xmin = 0, xmax = .4, ymin = pos1, ymax = pos2, fill = Sample), color = "black", size = 0.3, alpha = 0.2) + geom_text(aes(x = .2, y = x_median, label = Sample), vjust = .8, fontface = "bold", color = "black", angle = 90) + ylim(y_range) + theme_void() + theme(legend.position = "none") # 无刻度轴配置 Noax <- list( title = "", zeroline = FALSE, showline = FALSE, showticklabels = FALSE, showgrid = FALSE, showlegend = FALSE ) # 转plotly对象 fig_main <- ggplotly(p) fig_x <- ggplotly(ann_x) %>% layout(xaxis = Noax, yaxis = Noax) fig_y <- ggplotly(ann_y) %>% layout(xaxis = Noax, yaxis = Noax) # 第一步:纵向拼接顶部标注+主图,共享X轴 fig_col <- subplot( fig_x, fig_main, nrows = 2, shareX = TRUE, heights = c(0.1, 0.9), which_layout = 2, # 继承主图的布局配置 margin = 0.01 ) # 第二步:横向拼接上一步结果+右侧标注,共享Y轴 final_fig <- subplot( fig_col, fig_y, nrows = 1, shareY = TRUE, widths = c(0.9, 0.1), which_layout = 1, # 继承左侧整体的布局配置 margin = 0.01 ) # 输出最终图,R Markdown中直接调用final_fig即可 final_fig
效果说明
- 三个组件的坐标轴完全对齐,缩放、悬停等交互行为会同步触发
- 可以直接嵌入R Markdown文档输出html格式,完整保留交互能力
- 分组颜色自动统一,图例仅在主图底部显示一次,无重复
内容的提问来源于stack exchange,提问作者Zues
相关产品推荐
相关产品推荐

