Search code examples
pythoncolorsplotlyvisualizationplotly.graph-objects

How to specify discrete color of markers in Plotly.graph_objects?


After a lot of searching, I still have NOT found how to specify discrete color mapping for markers in a scatter figure that created by plotly.graph_objects (instead of plotly.express).

There are some docs about specifying discrete color mapping of plotly, but all of them are for px(plotly.express). e.g. Discrete colors in Python.

In the fact my requirement is very simple: I have a pd.Dataframe that has a column named 'label'. It stores my category info, and may has one of three values, i.e.[0, 1, 2].

I want markers be ploted as 'red' if the column 'label' has value 2, and 'yellow' for value 1, and 'blue' for value 0.

I mimiced px's sample and coded following:

from plotly.subplots import make_subplots
import plotly.graph_objects as go
fts['label'] = make3ClassLabel( df['target'] )

fig = make_subplots(rows=1, cols=2, shared_yaxes=True)

fig.add_trace(go.Scatter(x=fts['feat_x'], y=fts['feat_y0'],
                         mode='markers', marker_color=fts['label'],
            ############ following line doesn't work! #####################
                         color_discrete_sequence=['blue', 'yellow', 'red']),
            row=1, col=1)

fig.add_trace(go.Scatter(x=fts['feat_x'], y=fts['feat_y1'],
                         mode='markers',
            ############ also doesn't work! ###############################
                         marker={ 'color':fts['label'],
                                  'color_discrete_sequence':['blue', 'yellow', 'red'] }),
            row=1, col=2)

fig.update_traces(marker=dict(size=1, line=dict(width=0)))
fig.show()

Any hints or tips will be appretiated!!!


Solution

  • One way to do this is to create series for colors (using map) and then pass that series to marker_color:

    import plotly.graph_objects as go
    import pandas as pd
    
    df = pd.DataFrame({
        "x": [1,2,3,4,5,2],
        "y": [2,1,3,5,4,5],
        "label": [0, 0, 1, 2, 2, -1]
    })
    
    # label: color
    color_dict = {
        0: "red",
        1: "yellow",
        2: "lime"
    }
    
    # fillna is just-in-case for new/other labels
    color = df["label"].map(color_dict).fillna("white")
    
    fig = go.Figure()
    
    fig.add_trace(go.Scatter(
        x=df["x"], 
        y=df["y"],
        mode='markers',
        marker_color=color
    ))
    
    fig.update_layout(
        template="plotly_dark"
    )
    
    fig.show()
    

    Is that what you need? Please leave a comment.