pythonplotlybar-chartlegendplotly.graph-objects

A legend marker for each unique texture in the same bar trace, with Plotly Graph Objects in Python


I have the following code as example:

x=[1,2,3,4]
y=[2,2,4,3]
colors = ["blue","blue","orange","blue"]
textures = ["","","x",""]
myfig = go.Figure()
myfig.add_trace(go.Bar(x=x
                     ,y=y
                     ,showlegend=True
                     ,marker_color=colors
                     ,marker_pattern_shape=textures
                     ,name="my_trace"))
myfig.show()

Which produces the following figure:

Plot produced by the actual code

I want the legend to show two names:

I cannot add more traces to the plot, the point is to do it in the same unique trace.


Solution

  • I think plotly express would work well here. You will need to use color_discrete_map in addition to color because plotly will not interpret your list of colors as colors, but as unique strings (and assign its own default colors to each unique string regardless of the string itself). So what we will do is create a list of names (for the legend) to pass to the color parameter, and then map each name to the actual color using color_discrete_map.

    Similarly, you'll want to provide an argument for pattern_shape_sequence in addition to pattern_shape because pattern_shape_sequence will be what plotly uses to assign the actual textures.

    import numpy as np
    import plotly.express as px
    import plotly.graph_objects as go
    
    x=[1,2,3,4]
    y=[2,2,4,3]
    names = ["any","any","max","any"]
    colors = ["blue","blue","orange","blue"]
    color_discrete_map = {n:c for n,c in zip(names, colors)}
    textures = ["","","x",""]
    textures_sequence = np.unique(textures).tolist() # ['', 'x']
    
    myfig = px.bar(x=x, y=y, color=names, color_discrete_map=color_discrete_map, pattern_shape=textures, pattern_shape_sequence=textures_sequence)
    myfig.show()
    

    enter image description here