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

R plotly子图同时共享X轴Y轴实现带分组标注的交互式散点图

可交互分组标注散点图实现方案

核心思路

之前两次单独调用subplot无法同时共享双轴的核心原因是没有做嵌套拼接,正确的拼接逻辑如下:

  1. 先统一所有子图的X、Y轴范围,避免自动缩放导致错位
  2. 纵向拼接顶部X轴标注条 + 主体散点图,开启X轴共享
  3. 把上一步得到的整体图,和右侧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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 23:30:00