Plotly子图 - 图例项位于其图表旁边

3

使用plotly子图时,以下是一个典型示例(来自https://plotly.com/python/subplots/):

from plotly.subplots import make_subplots
import plotly.graph_objects as go

fig = make_subplots(rows=3, cols=1)
fig.append_trace(go.Scatter(x=[3, 4, 5], y=[1000, 1100, 1200]), row=1, col=1)
fig.append_trace(go.Scatter(x=[2, 3, 4], y=[100, 110, 120]), row=2, col=1)
fig.append_trace(go.Scatter(x=[0, 1, 2], y=[10, 11, 12]), row=3, col=1)
fig.update_layout(height=600, width=600, title_text="Stacked Subplots")
fig.show()

输入图片说明

当仅有三个数据系列时,这看起来还不错。但当有多达5个子图,每个子图都有几个数据系列时,就很难将图例中的项目与它们在图中出现的位置视觉关联。

是否可以将图例项向下移动,以使其与它们所在的图表对齐?

顺便说一下,我实际上是在R中工作,而不是Python,并且正在使用ggplotggplotly()生成单独图表的列表,然后像下面这样将它们组装起来:

  p <- subplot(plots, shareX=TRUE, nrows=length(plots))
  layout_args <- c(list(p,
                        title=title,
                        xaxis=list(title = 'Time (Local)'),
                        legend=list(orientation = 'v')),
                   yaxis_args)
  p <- do.call(layout, layout_args)
  htmlwidgets::saveWidget(htmlwidgets::as_widget(p), outfile)

但我猜想这个解决方案同样适用于R和Python。


可能需要使用注释而不是自动图例。这对您来说是否是可接受的解决方法?顺便说一下,直接在plotly API中完成此类操作可能是最简单的,而不是通过ggploty。 - dww
@dww 你所说的注释是指在图表本身上的标记,而不是侧边的图例吗?我认为在我的情况下这并不好,因为你会失去将它们用作跟踪开/关切换的能力。 - Ken Williams
用户 jrmisty 在 https://community.plotly.com/t/plotly-subplots-with-individual-legends/1754/18 上似乎已经找到了部分解决方案,但不幸的是,那里的切换行为是将单个图的所有曲线作为一组进行切换。离成功很近了... - Ken Williams
@KenWilliams - 这可以轻松地通过使用groupclick属性来实现,如layout(legend=list(tracegroupgap=150, groupclick="toggleitem")) - Martin
2个回答

2

有多种方法,我认为最简单的方法是添加额外的散点图,这些图具有线条的文本标签。文本散点图的xy是线条跟踪的x/y坐标。

from plotly.subplots import make_subplots
import plotly.graph_objects as go

fig = make_subplots(rows=3, cols=1)
fig.append_trace(go.Scatter(x=[3, 4, 5], y=[1000, 1100, 1200]), row=1, col=1)
fig.append_trace(go.Scatter(x=[2, 3, 4], y=[100, 110, 120]), row=2, col=1)
fig.append_trace(go.Scatter(x=[0, 1, 2], y=[10, 11, 12]), row=3, col=1)
fig.append_trace(go.Scatter(mode="text", text=["trace 1"], x=[5], y=[1200]), row=1, col=1)
fig.append_trace(go.Scatter(mode="text", text=["trace 2"],x=[4], y=[120]), row=2, col=1)
fig.append_trace(go.Scatter(mode="text", text=["trace 3"],x=[2], y=[12]), row=3, col=1)

fig.update_layout(height=600, width=600, title_text="Stacked Subplots", showlegend=False)
fig.show()

enter image description here


1
谢谢,Rob - 这种方法的缺点是您不能再使用图例作为跟踪的开关。对于我的绘图中的跟踪数量来说,这是一个重要的功能。 - Ken Williams
同意 - 另一个答案是我尝试过并发现更加“笨拙”的方法。你可以选择仍然在右上角显示图例,同时像我展示的那样在线条上标注标签。这样你就可以切换跟踪,并知道一条线是什么... - Rob Raymond

2

由于您提到需要一个交互式图例,可以切换跟踪内容的显示和隐藏,因此在子图上仅使用注释是不可能实现的。

这是一个有点混乱的解决方法,但是,为了实现这一点,您可以尝试使用tracegroupgap。缺点是您需要调整此选项提供的值以匹配窗口的大小。

p1 = plot_ly(data.frame(x=c(3, 4, 5), y=c(1000, 1100, 1200))) %>%
       add_lines(~x, ~y, legendgroup = 'group1', name = 'Trace 1')
p2 = plot_ly(data.frame(x=c(3, 4, 5), y=c(1000, 1100, 1200))) %>%
       add_lines(~x, ~y, legendgroup = 'group2', name = 'Trace 2')
p3 = plot_ly(data.frame(x=c(3, 4, 5), y=c(1000, 1100, 1200))) %>%
       add_lines(~x, ~y, legendgroup = 'group3', name = 'Trace 3')
subplot(p1,p2,p3,nrows = 3, shareX = TRUE) %>%
  layout(legend=list(tracegroupgap=150))

enter image description here


谢谢,我认为这是一个不错的处理方式。有没有办法将“legendgroup”应用于使用“ggplotly()”创建的现有绘图对象? - Ken Williams
请注意,如果您添加了layout(legend=list(tracegroupgap=150, groupclick="toggleitem"))中的groupclick属性,您可以选择和取消选择组中的单个跟踪,而不是全部或无。 - Martin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接