使用 Plotly 在手动生成的子图中添加 "facet_row labels"

Add "facet_row labels" in manually produced subplots with Plotly

考虑一个带有子图的图形,for example 像这样:

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()

我们得到这个

如何以与 plotly.express 相同的方式添加(手动)标签:

如果您检查 plotly express 示例中的 fig.layout,您会发现这些文本是 annotations

所以你可以做的是对每条轨迹使用 add_annotation

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.add_annotation(
    showarrow=False,
    text="smoker=Yes",
    textangle=90,
    x=1,
    xanchor='left',
    xref="paper",
    y=0.875,
    yanchor='middle',
    yref="paper",
)

fig.add_annotation(
    showarrow=False,
    text="smoker=No",
    textangle=90,
    x=1,
    xanchor='left',
    xref="paper",
    y=0.5,
    yanchor='middle',
    yref="paper",
)

fig.add_annotation(
    showarrow=False,
    text="smoker=Maybe",
    textangle=90,
    x=1,
    xanchor='left',
    xref="paper",
    y=0.125,
    yanchor='middle',
    yref="paper",
)

fig.update_layout(
    height=600,
    width=600,
    title_text="Stacked Subplots",
    legend=dict(yanchor="top", y=1, xanchor="right", x=1.3)
)
fig.show()

在上面的示例中,图例向右移动了一些,因此它没有覆盖注释。

要缩短代码,您可以将跟踪放在一个列表中并循环遍历它。对于每次迭代,您可以添加跟踪和注释,其中每个注释的 x 和 y 位置是相对于行(和列)的。

你的问题不是很清楚。您问的是标记由 go.Scatter() 条线组成的手动生成的子图。然后您请求使用 go.Histogram2d Plotly Express 但 不是 fig.add_annotations() 的解决方案。对我来说,听起来你可以问四个截然不同的问题。不过,对我来说,您似乎更愿意使用 px.density_hetmap() 来生成类似于 go.Histogram2d 的图。然后这一切都归结为拥有正确的数据结构并指定正确的 facet_row labels.

下面是 example 使用数据集``px.data.tips 生成此图:

如果我的假设是正确的,那么这正是您的目标。

完整代码:

import plotly.express as px
df = px.data.tips()

fig = px.density_heatmap(df, x="total_bill", y="tip", facet_row="sex", facet_col="smoker")
fig.show()

编辑:每一行可以有不同的 y-binning 吗?

是的,我想是的。当然有点取决于你的意思。但是您可以通过以下方式自由定义所有轴的分箱:

fig.data[n].update(xbins = {'end': 155, 'size': 5, 'start': 0}, ybins = {'end': 11, 'size': 1, 'start': 0})

其中 n 在这种情况下是 [0,3] 中的一个元素,对应于子图的数量。您还必须指定:

fig.update_xaxes(matches=None)
fig.update_yaxes(matches=None)

或者你会得到一些非常时髦的结果。

将下面的图和相应的代码片段与上面的进行比较,以查看示例:

fig.data[3].update(xbins = {'end': 75, 'size': 5, 'start': 0}, ybins = {'end': 25, 'size': 1, 'start': 0})

情节 2:

情节 2 的完整代码:

import plotly.express as px
df = px.data.tips()

fig = px.density_heatmap(df, x="total_bill", y="tip", facet_row="sex", facet_col="smoker")
fig.update_xaxes(matches=None)
fig.update_yaxes(matches=None)
fig.data[3].update(xbins = {'end': 75, 'size': 5, 'start': 0}, ybins = {'end': 25, 'size': 1, 'start': 0})
fig.for_each_yaxis(lambda yax: yax.update(showticklabels = True))


fig.show()