✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🧬 Learn how to build RNA-Seq data apps with Python & Dash. Register for the May 20 Webinar!

Subplots and customize colorbar

Hi everyone,

I started using plotly weeks ago, and first I would thank you for the wonderfull job you’ve done so far.
Concerning my post, I am facing an issue I can’t resolved.
I am using subplots to have different scatter plots and I want to display a shared colorbar with annual range (from january to december), to color my markers depending on the month they are related to.
I found this usefull thread (Manually customize colorbar - scatter python) but my problem vary a little and I’m stuck right now.

First : whatever I do the markers are colored with default colorscale : writing “color = myData[“date”].month” or not does not change anything on the rendering…

Second : i’m using a trace on every row of my dataset because I have multiple y-values for each x-values (in the code : 1 subplot per element, several points per element, each point (x value) has several y-values), and from what I’ve read on the forum it is the only way to display this king of data. The problem is if I define the colorbar in the trace statement, it takes a long time to display the figure due to I guess the building of the colorbar for each trace (meaning each row of my dataset… = 137). Because of that, I tried to use a shared colorbar (using coloraxis) but doing this the colorbar is not displayed anymore…

You can find my code below and screenshot of the figure.

Code where colobar is define within the trace statement

fig = make_subplots(
        rows = 4, 
        cols = 3, 
        subplot_titles=elementName,
        vertical_spacing=0.1)

colorName = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec']
colorVals = list(range(len(colorName))) 

colorScale = [
        [0,'rgb(16,50,141)'],
        [0.0833,'rgb(16,50,141)'],#jan
        [0.0833,'rgb(23,97,93)'],
        [0.1667,'rgb(23,97,93)'],#fev
        [0.1667,'rgb(63,165,23)'],
        [0.25,'rgb(63,165,23)'],     #mar   
        [0.25,'rgb(159,179,12)'],
        [0.3333,'rgb(159,179,12)'], #avr
        [0.3333,'rgb(228,188,3)'],
        [0.4167,'rgb(228,188,3)'], #mai
        [0.4167,'rgb(253,186,0)'],
        [0.5,'rgb(253,186,0)'], #juin
        [0.5,'rgb(221,87,0)'],
        [0.5833,'rgb(221,87,0)'], #juil
        [0.5833,'rgb(200,25,0)'],
        [0.6667,'rgb(200,25,0)'], #aout
        [0.6667,'rgb(166,0,28)'],
        [0.75,'rgb(166,0,28)'], #sept
        [0.75,'rgb(119,0,77)'],
        [0.8333,'rgb(119,0,77)'], #oct
        [0.8333,'rgb(69,0,129)'],
        [0.9167,'rgb(69,0,129)'], #nov
        [0.9167,'rgb(30,0,170)'],
        [1,'rgb(30,0,1170)'] #dec
        ]

i = 1
j = 0

for element in elements:
    j += 1
    for point in points :
        dataFilter = data[data["name"] == point]
        for index, row in dataFilter.iterrows() :
            fig.add_trace(
                go.Scatter(
                        x=[x[point]], 
                        y=[row[element]],
                        mode = 'markers',
                        name = point,
                        marker= dict(
                                cmin = -0.5,
                                cmax = 11.5,
                                colorscale = colorScale,
                                colorbar = dict(
                                        title = 'Mois',
                                        tickvals = colorVals,
                                        ticktext = colorName,
                                        ),
                                symbol = symbolFormat[element]['markerSymbol'],
                                size = 10,
                                color = row["date"].month
                                )
                        ),
                                
                row = i,
                col = j)
    fig.update_yaxes(
            linecolor = 'black',
            linewidth = 1,
            mirror = True,
            gridcolor = 'lightgrey',
            gridwidth = 1,                    
            row=i, 
            col=j)
    
    fig.update_xaxes(
            linecolor = 'black',
            linewidth = 1,
            mirror = True,
            ticks="outside",
            gridcolor = 'lightgrey',
            gridwidth = 1,
            row=i, 
            col=j)    
       
    if(j == 3) :
        j = 0
        i += 1

fig.update_layout(
        showlegend = False,
        paper_bgcolor = 'rgba(0,0,0,0)',
        plot_bgcolor = 'rgba(0,0,0,0)', 
        )
fig.show()

Rendering

Code using coloraxis

fig = make_subplots(
        rows = 4, 
        cols = 3, 
        subplot_titles=elementName,
        vertical_spacing=0.1)

colorName = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec']
colorVals = list(range(len(colorName))) 

colorScale = [
        [0,'rgb(16,50,141)'],
        [0.0833,'rgb(16,50,141)'],#jan
        [0.0833,'rgb(23,97,93)'],
        [0.1667,'rgb(23,97,93)'],#fev
        [0.1667,'rgb(63,165,23)'],
        [0.25,'rgb(63,165,23)'],     #mar   
        [0.25,'rgb(159,179,12)'],
        [0.3333,'rgb(159,179,12)'], #avr
        [0.3333,'rgb(228,188,3)'],
        [0.4167,'rgb(228,188,3)'], #mai
        [0.4167,'rgb(253,186,0)'],
        [0.5,'rgb(253,186,0)'], #juin
        [0.5,'rgb(221,87,0)'],
        [0.5833,'rgb(221,87,0)'], #juil
        [0.5833,'rgb(200,25,0)'],
        [0.6667,'rgb(200,25,0)'], #aout
        [0.6667,'rgb(166,0,28)'],
        [0.75,'rgb(166,0,28)'], #sept
        [0.75,'rgb(119,0,77)'],
        [0.8333,'rgb(119,0,77)'], #oct
        [0.8333,'rgb(69,0,129)'],
        [0.9167,'rgb(69,0,129)'], #nov
        [0.9167,'rgb(30,0,170)'],
        [1,'rgb(30,0,1170)'] #dec
        ]

i = 1
j = 0
>
for element in elements:
    j += 1
    for point in points :
        dataFilter = data[data["name"] == point]
        for index, row in dataFilter.iterrows() :
            fig.add_trace(
                go.Scatter(
                        x=[x[point]], 
                        y=[row[element]],
                        mode = 'markers',
                        name = point,
                        marker= dict(
                                coloraxis = "coloraxis",
                                symbol = symbolFormat[element]['markerSymbol'],
                                size = 10,
                                color = row["date"].month
                                )
                        ),
                                
                row = i,
                col = j)
    fig.update_yaxes(
            linecolor = 'black',
            linewidth = 1,
            mirror = True,
            gridcolor = 'lightgrey',
            gridwidth = 1,                    
            row=i, 
            col=j)
    
    fig.update_xaxes(
            linecolor = 'black',
            linewidth = 1,
            mirror = True,
            ticks="outside",
            gridcolor = 'lightgrey',
            gridwidth = 1,
            row=i, 
            col=j)    
       
    if(j == 3) :
        j = 0
        i += 1

fig.update_layout(
        coloraxis = dict(
                showscale = True,
                colorscale = colorScale,
                colorbar = dict(
                        title = 'Mois',
                        ticktext = colorName,
                        tickvals = colorVals
                        ),
                ),
        showlegend = False,
        paper_bgcolor = 'rgba(0,0,0,0)',
        plot_bgcolor = 'rgba(0,0,0,0)', 
        )
fig.show()

Rendering

Thanks in advance helping me on this ! Feel free to ask for more details.

Ok I found a workaround to solve my problem :

I created a color map :

colorMap = {
        1:'rgb(16,50,141)',
        2:'rgb(23,97,93)',
        3:'rgb(63,165,23)',
        4:'rgb(159,179,12)',
        5:'rgb(228,188,3)',
        6:'rgb(253,186,0)',
        7:'rgb(221,87,0)',
        8:'rgb(200,25,0)',
        9:'rgb(166,0,28)',
        10:'rgb(119,0,77)',
        11:'rgb(69,0,129)',
        12:'rgb(30,0,170)',
        }

And just maping it with the color properties of the markers :

color = colorMap[point['date'].month]

And for the colorbar I used this workaround :

Sometimes no need of seeking too much complexity :upside_down_face: