0

I want to follow up on this post: Plotly: How to colorcode plotly graph objects bar chart using Python?.

When using plotly express, and specifying 'color', the legend is correctly produced as seen in the post by vestland.

This is my plotly express code:

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

But when using go.Bar, the legend is incorrectly displayed as illustrated here:

enter image description here

This is my code using graph objects:

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

I'm learning how to use FigureWidget and it seems it can't use plotly express so I have to learn how to use graph objects to plot. How do I link the legend to the data such that it works like the plotly express example in vestland's post.

1 Answer 1

2

This really comes down to understanding what a high level API (plotly express) does. When you specify color in px if it is categorical it creates a trace per value of categorical. Hence the below two ways of creating a figure are mostly equivalent. The legend shows an item for each trace, not for each 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

supplementary based on comments

  • you do not have to use graph objects if you are using FigureWidget() as demonstrated by second figure, create with plotly express and then generate FigureWidget()
  • for continuous data normal pattern is to use a single trace and a colorbar (also demonstrated in second figure). However if you want a discrete legend, create a trace per value in c_data and use 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()

enter image description here

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the reply. I'm new to plotly and also not a developer. But can you also explain how it works with continuous data? I really can't find anything in the documentation to figure this out.
with continuous data, typically a colorbar is used which for a range of values assigns a color. so typically with a continuous series you do not use a legend like in your screen shot but a colorbar. the permutations of options is large, I can only explain in abstract way as you have not provided how you generated your bar figure
I've edited my original post to include my code sample. I basically tried to replicate the parameters in plotly express for the graph object.
ok - have added supplementary update to show a) making a continuous color scaler discrete in graph objects with legend showing a value for each discrete value b) how to use continuous with plotly express and figure widget
Thanks! Didn't realise I don't have to use graph objects when using FigureWidget(). The documentation somehow implied to me I can't use plotly express as it only has the graph object example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.