pythonplotlyplotly.graph-objects

Python Plotly: Coloring graph_object lines according to variable value?


I’m trying to plot multiple traces on one figure and color the lines according to a continuous color scale using plotly.graph_objects. I’m having trouble getting them to color correctly. Example below:


import plotly.graph_objects as go
import numpy as np

data = np.array([[0, 1, 2, 3, 4, 5],
[0, 1.1, 2.1, 3.1, 4.1, 5.1],
[1, 2, 3, 4, 5, 6],
[2, 3, 4, 5, 6, 7],
[2, 3.1, 4.1, 5.1, 6.1, 7.1],
[3, 4, 5, 6, 7, 8]]) # 2D array of data, each row are the y values of a different trace

vals = [0, 0, 1, 2, 2, 3] # desired values for color scale

nums = [1, 2, 3, 4, 5] # x-values to plot lines on

fig = go.Figure()
for i, row in enumerate(data):
fig.add_trace(go.Scatter(x=nums, y=row, name=vals[i], mode='lines',
              marker=dict(color=vals, cmax=3, cmin=0, colorscale='Viridis')))

fig.show()

I would like for the color of each trace to be determined by vals, so the first two traces would have the same color (purple on the Viridis scale) since they have the same vals[i] value, the fourth and fifth traces would also have matching colors, and the sixth trace would be the max value of the color scale (yellow on the Viridis scale).

As the code above is, it just uses the default discrete color map and traces with the same vals are not the same color.

Thanks!


Solution

  • From what I can tell, the marker dict will only set the color of the markers, not the lines. And I don't see a way to set the line color in a similar way -- I believe line colors are required to be rgb values (or keyword color names).

    You can however, use the plotly.express.colors.sample_colorscale function to pre-sample a colormap to get rgb values to use with your lines. Just be sure to normalize your vals between 0 and 1 before calling it.

    from plotly.express.colors import sample_colorscale
    
    import plotly.graph_objects as go
    import numpy as np
    
    data = np.array([[0, 1, 2, 3, 4, 5],
    [0, 1.1, 2.1, 3.1, 4.1, 5.1],
    [1, 2, 3, 4, 5, 6], 
    [2, 3, 4, 5, 6, 7], 
    [2, 3.1, 4.1, 5.1, 6.1, 7.1],
    [3, 4, 5, 6, 7, 8]]) # 2D array of data, each row are the y values of a different trace
    
    vals = [0, 0, 1, 2, 2, 3] # desired values for color scale
    
    # sample from the colormap, using normalized values between 0 and 1:
    normalized_vals = [(v - min(vals))/(max(vals)-min(vals)) for v in vals]
    colors = sample_colorscale('Viridis', normalized_vals)
    
    nums = [1, 2, 3, 4, 5] # x-values to plot lines on
    
    fig = go.Figure()
    for i, row in enumerate(data):
        fig.add_trace(go.Scatter(x=nums, y=row, 
                                 name=vals[i], mode='lines',
                                 line=dict(color=colors[i])))
    
    
    fig.show()