使用标记颜色时如何格式化图例?

How to format plotly legend when using marker color?

我想跟进这个post:

当使用 plotly express 并指定 'color' 时,图例会正确生成,如 vestland 在 post 中所见。

这是我的情节表达代码:

data = {'x_data': np.random.random_sample((5,)),
        'y_data': ['A', 'B', 'C', 'D', 'E'],
        'c_data': np.random.randint(1, 100, size=5)
       }

df = pd.DataFrame(data=data)

fig = px.bar(df,
             x='x_data',
             y='y_data',
             orientation='h',
             color='c_data',
             color_continuous_scale='YlOrRd'
            )
fig.show()

但是当使用 go.Bar 时,图例显示不正确,如下所示:

这是我使用图形对象的代码:

bar_trace = go.Bar(name='bar_trace',
               x=df['x_data'],
               y=df['y_data'],
               marker={'color': df['c_data'], 'colorscale': 'YlOrRd'},
               orientation='h'
              )

layout = go.Layout(showlegend=True)

fig = go.FigureWidget(data=[bar_trace], layout=layout)

fig.show()

我正在学习如何使用 FigureWidget,它似乎不能使用 plotly express,所以我必须学习如何使用图形对象进行绘图。我如何 link 数据的图例,使其像 vestland 的 post.

中的 plotly express 示例一样工作

这实际上归结为理解高水平 API(plotly express)的作用。当您在 px 中指定 color 时,如果它是分类的,它会为每个分类值创建一个跟踪。因此,以下两种创建图形的方法基本上是等价的。图例为每条轨迹显示一个项目,而不是为每种颜色显示一个项目。

import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import numpy as np

df = pd.DataFrame({"x":np.linspace(0,10,10), "y":np.linspace(5,15,10), "color":np.random.choice(list("ABCD"),10)})

px.bar(df, x="x", y="y", color="color", orientation="h").show()

fig = go.Figure()
for g in df.groupby("color"):
    fig.add_trace(go.Bar(x=g[1]["x"], y=g[1]["y"], name=g[0], orientation="h"))

    
fig

根据评论补充

  • 如果您使用 FigureWidget(),则不必使用 graph objects,如第二个图所示,使用 plotly express[=32 创建=] 然后生成 FigureWidget()
  • 对于连续数据,正常模式是使用单个迹线和颜色条(也在第二张图中演示)。但是,如果您想要离散图例,请在 c_data 中为每个值创建一个轨迹并使用 https://plotly.com/python-api-reference/generated/plotly.colors.html sample_colorscale()
import plotly.express as px
import plotly.colors
import plotly.graph_objects as go
import numpy as np
import pandas as pd

# simulate data frame...
df = pd.DataFrame(
    {
        "x_data": np.linspace(0, 10, 10),
        "y_data": np.linspace(5, 15, 10),
        "c_data": np.random.randint(0, 4, 10),
    }
)

# build a trace per value in c_data using graph objects ... correct legend !!??
bar_traces = [
    go.Bar(
        name="bar_trace",
        x=d["x_data"],
        y=d["y_data"],
        marker={
            "color": plotly.colors.sample_colorscale(
                "YlOrRd",
                d["c_data"] / df["c_data"].max(),
            )
        },
        orientation="h",
    )
    for c, d in df.groupby("c_data")
]

layout = go.Layout(showlegend=True)

fig = go.FigureWidget(data=bar_traces, layout=layout)
fig.show()

fig = px.bar(
    df,
    x="x_data",
    y="y_data",
    color="c_data",
    orientation="h",
    color_continuous_scale="YlOrRd",
)
fig = go.FigureWidget(data=fig.data, layout=fig.layout)
fig.show()