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

如何基于Plotly的subplot实现各子图带独立图例的分面图?

问题:Plotly子图实现独立图例并支持PDF导出

我之前用htmltools结合Plotly生成了分面条形图,代码如下:

library(plotly)
library(htmltools)

legend <- list(orientation = "v", y = 1, x = .85)

fig1 <- plot_ly(
  x = c("orangutans1", "orangutans", "monkeys"),
  y = c(10, 1, 3),
  name = "SF Zoo",
  type = "bar", marker = list(color = "blue"),
  legendgroup = "1"
) |>
  layout(showlegend = TRUE, legend = legend, 
         title = 'Title 1')

fig2 <- plot_ly(
  x = c("giraffes", "orangutans", "monkeys"),
  y = c(10, 84, 32),
  name = "SF Zoo",
  type = "bar", marker = list(color = "royalblue"),
  legendgroup = "2"
) |>
  layout(showlegend = TRUE, legend = legend,title = 'Title 2')

fig3 <- plot_ly(
  x = c("giraffes", "orangutans", "monkeys"),
  y = c(5, 14, 27),
  name = "SF Zoo",
  type = "bar", marker = list(color = "green")
) |>
  layout(showlegend = TRUE, legend = legend,title = 'Title 3')

fig4 <- plot_ly(
  x = c("giraffes", "orangutans", "monkeys"),
  y = c(22, 24, 67),
  name = "SF Zoo",
  type = "bar", marker = list(color = "black")
) |>
  layout(showlegend = TRUE, legend = legend,title = 'Title 4')

htmltools::div(
  crosstalk::bscols(
    fig1, fig2
  ),
  crosstalk::bscols(
    fig3, fig4
  )
) |>
  htmltools::browsable()

这种方式生成的是四个独立图表,虽然每个子图配有独立图例,但无法正常导出为PDF格式。现在需要改用Plotly的subplot功能,实现带独立图例的分面图,同时支持PDF导出。


解决方案

核心是通过subplot整合所有子图为单个Plotly对象,配合legendgroup和自定义图例位置,实现每个子图的独立图例,具体代码如下:

library(plotly)

# 定义统一的图例布局(可按需调整位置)
get_legend_layout <- function() {
  list(orientation = "v", y = 0.95, x = 0.8, 
       tracegroupgap = 0, bgcolor = "rgba(255,255,255,0.8)")
}

# 创建子图1
fig1 <- plot_ly(
  x = c("orangutans1", "orangutans", "monkeys"),
  y = c(10, 1, 3),
  name = "SF Zoo",
  type = "bar", marker = list(color = "blue"),
  legendgroup = "fig1"  # 唯一图例组标识
) |>
  layout(
    title = list(text = 'Title 1', x = 0.05),
    showlegend = TRUE,
    legend = get_legend_layout(),
    margin = list(l = 50, r = 80, t = 40, b = 40)  # 预留图例空间
  )

# 创建子图2
fig2 <- plot_ly(
  x = c("giraffes", "orangutans", "monkeys"),
  y = c(10, 84, 32),
  name = "SF Zoo",
  type = "bar", marker = list(color = "royalblue"),
  legendgroup = "fig2"
) |>
  layout(
    title = list(text = 'Title 2', x = 0.05),
    showlegend = TRUE,
    legend = get_legend_layout(),
    margin = list(l = 50, r = 80, t = 40, b = 40)
  )

# 创建子图3
fig3 <- plot_ly(
  x = c("giraffes", "orangutans", "monkeys"),
  y = c(5, 14, 27),
  name = "SF Zoo",
  type = "bar", marker = list(color = "green"),
  legendgroup = "fig3"
) |>
  layout(
    title = list(text = 'Title 3', x = 0.05),
    showlegend = TRUE,
    legend = get_legend_layout(),
    margin = list(l = 50, r = 80, t = 40, b = 40)
  )

# 创建子图4
fig4 <- plot_ly(
  x = c("giraffes", "orangutans", "monkeys"),
  y = c(22, 24, 67),
  name = "SF Zoo",
  type = "bar", marker = list(color = "black"),
  legendgroup = "fig4"
) |>
  layout(
    title = list(text = 'Title 4', x = 0.05),
    showlegend = TRUE,
    legend = get_legend_layout(),
    margin = list(l = 50, r = 80, t = 40, b = 40)
  )

# 组合为2行2列的子图
combined_fig <- subplot(
  fig1, fig2,
  fig3, fig4,
  nrows = 2,
  shareX = FALSE,  # 按需设置是否共享X轴
  shareY = FALSE,  # 按需设置是否共享Y轴
  margin = 0.08  # 子图间间距
) |>
  layout(title = list(text = "分面条形图(带独立图例)", x = 0.5))

# 查看交互式图表
combined_fig

# 导出为PDF(需提前安装orca工具)
# plotly::orca(combined_fig, "subplot_with_legends.pdf")

关键说明

  • 图例独立性:给每个子图设置唯一legendgroup,确保图例互不干扰,各自独立显示
  • 图例位置控制:通过legend参数的x/y坐标,将图例固定在子图内部右侧,避免子图重叠
  • 间距调整:subplot的margin控制子图间距离,每个子图的layout$margin预留图例空间
  • PDF导出:生成的combined_fig是单个Plotly对象,可直接用orca()命令导出为PDF,或在RStudio中通过「Export」按钮导出

内容的提问来源于stack exchange,提问作者silent_hunter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 18:17:54