Update add_hline with Dropdown menu

Hello there!

I’m looking to ‘link’ my Dropdowns (buttons) to my hlines. For now these lines don’t update with the other traces (scatter and bar).
To explain :

  • I have one button to select the column to plot
  • The second button is for selecting the ‘sportif’ I want (like an ID)

Here is my code:

fig = go.Figure()

fig.add_scatter(
        x = df_plot[df_plot['sportif'] == 'Joueur-10']['dateSeance'], 
        y = df_plot[df_plot['sportif'] == 'Joueur-10']['intensitemax'], 
        mode='lines+markers', fill='tozeroy', marker_color='#576DF3', 
        marker=dict(opacity=0.8,
                    size=3
                   ),
        line=dict(width=1
                 ),
        name='Seances'
)

fig.add_bar(
        x = df_plot[(df_plot['sportif'] == 'Joueur-10') & (df_plot['nomSeance'] == 'Match')]['dateSeance'], 
        y = df_plot[(df_plot['sportif'] == 'Joueur-10') & (df_plot['nomSeance'] == 'Match')]['intensitemax'],
        marker_color='#576DF3', 
        name='Matchs', opacity=1
)

fig.update_xaxes(
    tickangle=45, dtick='L1'
)

fig.add_hline(
    y=df_plot[df_plot['sportif'] == 'Joueur-10']['intensitemax'].median(), 
    line_width=1, line_dash='longdash'
)

fig.add_hline(
    y=df_plot[df_plot['sportif'] == 'Joueur-10']['intensitemax'].quantile(0.75), 
    line_width=1, line_dash='dot'
)

fig.add_annotation(
    dict(
        font=dict(color="black",size=10), x=1.05, 
        y=df_plot[df_plot['sportif'] == 'Joueur-10']['intensitemax'].median()+0.1,
        showarrow=False, text='<b>50%</b>', xref="paper", yref="y"
    )
)

fig.add_annotation(
    dict(
        font=dict(color="mediumblue",size=10), x=1.05, 
        y=df_plot[df_plot['sportif'] == 'Joueur-10']['intensitemax'].quantile(0.75)+0.1,
        showarrow=False, text='<b>75%</b>', xref="paper", yref="y"
    )
)

fig.update_layout(
    xaxis=dict(
        rangeselector=dict(
            buttons=list([
                dict(count=14,
                     label='2w',
                     step='day'),
                dict(count=1,
                     label='1m',
                     step='month'),
                dict(count=2,
                     label='2m',
                     step='month'),
                dict(count=6,
                     label='6m',
                     step='month'),
                dict(count=1,
                     label='1y',
                     step='year'),
                dict(step='all')
            ])
        ),
        rangeslider=dict(
            visible=True
        ),
        type="date"
    )
)

button1 = [dict(method = 'update',
                args = [{'y': [df_plot[df_plot['sportif'] == 'Joueur-10'][c],
                               df_plot[(df_plot['sportif'] == 'Joueur-10') & (df_plot['nomSeance'] == 'Match')][c],
                               df_plot[df_plot['sportif'] == 'Joueur-10'][c].median(),
                               df_plot[df_plot['sportif'] == 'Joueur-10'][c].median()+0.1]
                        }],
                label = c) for c in marqueurs]

button2 = [dict(method = 'update',
                args = [{'y': [df_plot[df_plot['sportif'] == n]['intensitemax'],
                               df_plot[(df_plot['sportif'] == n) & (df_plot['nomSeance'] == 'Match')]['intensitemax'],
                               df_plot[df_plot['sportif'] == n]['intensitemax'].median(),
                               df_plot[df_plot['sportif'] == n]['intensitemax'].median()+0.1]
                        }],
                label = n) for n in df_plot.sportif.unique()]

fig.update_layout(width=1000, height=800,
                  yaxis=dict(range=[0,10]),
                  template='plotly_white',
                  autosize=False,
                  updatemenus=[
                      dict(
                          buttons=button1,
                          active=0,
                          x=0.5, y=1.085,
                          xanchor='left', yanchor='top'
                      ),
                      dict(
                          buttons=button2,
                          active=0,
                          x=0.3, y=1.085,
                          xanchor='left',
                          yanchor='top'                         
                      )
                              ]
                 )

fig.show()

As you can see, I tried to code for one hline (the ‘median’ one). But when I select a new column or ‘sportif’ with my dropdwns the line stays the same.

And here is my fig:

Thanks all for your help :love_you_gesture:

I have a similar question. Just wondering if there is a solution already? Thank you.

Yes, I finally used ipywidgets :

joueurs_dp = widgets.Dropdown(description='Joueur :   ',
                           value=Joueurs[0],
                           options=Joueurs
                          )

marqueurs_dp = widgets.Dropdown(description='Marqueur :   ', 
                                value=marqueurs[0],
                                options=marqueurs
                               )

trace1 = go.Scatter(x=df_plot.loc[df_plot['sportif']==Joueurs[0],'dateSeance'], 
                    y=df_plot.loc[df_plot['sportif']==Joueurs[0], marqueurs[0]],
                    mode='lines+markers', fill='tozeroy', marker_color='#576DF3',
                    marker=dict(opacity=0.8,size=3), line=dict(width=1),
                    name='Seances')

trace2 = go.Bar(x=df_plot.loc[(df_plot['sportif']==Joueurs[0])&(df_plot['nomSeance']=='Match'),'dateSeance'],
                y=df_plot.loc[(df_plot['sportif']==Joueurs[0])&(df_plot['nomSeance']=='Match'), marqueurs[0]],
                marker_color='#576DF3',
                name='Matchs', opacity=1)

trace3 = go.Scatter(x=df_plot.loc[df_plot['sportif']==Joueurs[0],'dateSeance'], 
                    y=df_plot.loc[df_plot['sportif']==Joueurs[0], marqueurs[0]+'_median'],
                    mode='lines', name='Median',
                    line=dict(width=0.7, color='black', dash='longdash'))

trace4 = go.Scatter(x=df_plot.loc[df_plot['sportif']==Joueurs[0],'dateSeance'], 
                    y=df_plot.loc[df_plot['sportif']==Joueurs[0], marqueurs[0]+'_p75'],
                    mode='lines', name='p75',
                    line=dict(width=0.7, color='black', dash='dot'))

g = go.FigureWidget(data=[trace1,trace2, trace3, trace4], layout=go.Layout(barmode='overlay'))

def response(change):
    dff = df_plot.copy()
    dff = df_plot[df_plot['sportif'] == joueurs_dp.value]
        
    a = pd.DataFrame(data={'dateSeance': pd.date_range(dff.dateSeance.min(), dff.dateSeance.max())})
    b = pd.merge(dff, a, how='outer', on='dateSeance').sort_values(by='dateSeance').reset_index().drop(columns='index')
    [b[col].fillna(0, inplace=True) for col in marqueurs]
    [b[col+'_median'].fillna(b[col+'_median'].median(), inplace=True) for col in marqueurs]
    [b[col+'_p75'].fillna(b[col+'_p75'].median(), inplace=True) for col in marqueurs]
    
    df_m = dff[dff['nomSeance']=='Match']
    c = pd.DataFrame(data={'dateSeance': pd.date_range(dff.dateSeance.min(), dff.dateSeance.max())})
    d = pd.merge(df_m, c, how='outer', on='dateSeance').sort_values(by='dateSeance').reset_index().drop(columns='index')
    [d[col].fillna(0, inplace=True) for col in marqueurs]
    d['nomSeance'].fillna('Match', inplace=True)
    d['sportif'].fillna(joueurs_dp.value, inplace=True)
    d['duree'] = d['duree'].astype('Int64')
    d['Annee'] = d.dateSeance.dt.year.astype(str)
    d['Semaine'] = d.dateSeance.dt.isocalendar().week.astype(str).str.pad(width=2, fillchar='0')
    d['numsemaine'] = d['Annee'].str.cat(d['Semaine'], sep='-')
    d.drop(columns=['Annee', 'Semaine'], inplace=True)

    x1 = b['dateSeance']
    y1 = b[marqueurs_dp.value]
    x2 = d.loc[d['nomSeance']=='Match', 'dateSeance']
    y2 = d.loc[d['nomSeance']=='Match', marqueurs_dp.value]
    y3 = b[marqueurs_dp.value+'_median']
    y4 = b[marqueurs_dp.value+'_p75']

    with g.batch_update():
        g.data[0].x = x1
        g.data[0].y = y1
        g.data[1].x = x2
        g.data[1].y = y2
        g.data[2].x = x1
        g.data[2].y = y3
        g.data[3].x = x1
        g.data[3].y = y4
        g.layout.barmode = 'overlay'

joueurs_dp.observe(response)
marqueurs_dp.observe(response)

g.update_layout(width=1000, height=700,
                  yaxis=dict(range=[0,10]),
                  template='plotly_white',
                  autosize=False)

g.update_xaxes(tickangle=45, dtick='L1')

g.update_layout(xaxis=dict(rangeselector=dict(buttons=
                                              list([dict(count=14, label='2s', step='day'),
                                                    dict(count=1, label='1m', step='month'),
                                                    dict(count=2, label='2m', step='month'),
                                                    dict(count=6, label='6m', step='month'),
                                                    dict(count=1, label='1a', step='year'),
                                                    dict(step='all')])
                                             ), rangeslider=dict( visible=True), type="date"))

container = widgets.HBox([joueurs_dp, marqueurs_dp])
widgets.VBox([container, g])```