如何基于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
相关产品推荐
相关产品推荐

