Search code examples
pythonplotlyplotly-python

Color specific points in a plotly express strip plot


Let's take this sample dataframe :

import random

df=pd.DataFrame({'Id':list(range(1,101)), 'Value':[random.randint(0,50) for i in range(100)]})

I would like to create a plotly express strip plot in which id 5 and 10 are colored in red and the others in blue. I built the following function :

import plotly.express as px

def strip_plotly(df,col_value,col_hover=[],col_color=None,L_color=[]):
        
    if col_color is not None :
        L_color = ["red" if i in L_color else "blue" for i in df[col_color].values]
    else :
        L_color = ["blue"]*len(df.index)
        
    fig = px.strip(df, y=col_value,hover_data = col_hover,color_discrete_sequence = L_color)

    fig.update_layout({
            'plot_bgcolor': 'rgba(0,0,0,0)',
            'paper_bgcolor': 'rgba(0,0,0,0)',
        },
        hoverlabel=dict(
            #bgcolor="white", 
            font_size=12, 
            #font_family="Rockwell"
        ),
        xaxis={
            'title':"x",
            #'type':'log'
        },
        yaxis={'title':"y"},
        title={
            'text': "strip plot for stackoverflow",
            #'y':0.95,
            'x':0.5,
            'xanchor': 'center',
            'yanchor': 'top'}
    )

    fig.update_xaxes(showspikes=True, spikecolor = 'black', showline=True, linewidth=1,linecolor='black',
                     ticks = "outside", tickwidth = 1, tickcolor = 'black',ticklen = 5)
    fig.update_yaxes(showspikes=True, spikecolor = 'black', showline=True, linewidth=1,linecolor='black',
                     ticks = "outside", tickwidth = 1, tickcolor = 'black',ticklen = 5)
    
    fig.show()

But when I run the function :

strip_plotly(df,"Value",col_hover=["Id"],col_color="Id",L_color=[5,10])

I get only blue points (ids 5 and 10 are not red). Would you please explain me what's wrong ? enter image description here


Solution

  • import random
    import plotly.express as px
    import numpy as np
    import pandas as pd
    
    df=pd.DataFrame({'Id':list(range(1,21)), 'Value':[random.randint(0,50) for i in range(20)]})
    
    
    def strip_plotly(df,col_value,col_hover=[],col_color=None,L_color=[]):
        L_color = np.where(df["Id"].isin([5,10]), "red", "blue")
    
        # need two traces as color is in marker https://plotly.github.io/plotly.py-docs/generated/plotly.graph_objects.box.marker.html
        fig = px.strip(df.loc[L_color=="blue"], y=col_value,hover_data = col_hover,color_discrete_sequence = ["blue"])
        fig = fig.add_traces(px.strip(df.loc[L_color=="red"], y=col_value,hover_data = col_hover,color_discrete_sequence = ["red"]).data)
        fig = fig.update_traces(offsetgroup="1")
    
        fig.update_layout({
                'plot_bgcolor': 'rgba(0,0,0,0)',
                'paper_bgcolor': 'rgba(0,0,0,0)',
            },
            hoverlabel=dict(
                #bgcolor="white", 
                font_size=12, 
                #font_family="Rockwell"
            ),
            xaxis={
                'title':"x",
                #'type':'log'
            },
            yaxis={'title':"y"},
            title={
                'text': "strip plot for stackoverflow",
                #'y':0.95,
                'x':0.5,
                'xanchor': 'center',
                'yanchor': 'top'}
        )
    
        fig.update_xaxes(showspikes=True, spikecolor = 'black', showline=True, linewidth=1,linecolor='black',
                         ticks = "outside", tickwidth = 1, tickcolor = 'black',ticklen = 5)
        fig.update_yaxes(showspikes=True, spikecolor = 'black', showline=True, linewidth=1,linecolor='black',
                         ticks = "outside", tickwidth = 1, tickcolor = 'black',ticklen = 5)
        
        return fig.show()
        
    strip_plotly(df,"Value",col_hover=["Id"],col_color="Id",L_color=[5,10])
    
    
    

    enter image description here