Plotly update customdata with dropdown button

Hello eveyone!

I have a quick question: basically I have created a plot with some hover information and I have a dropdown button, where the user can chose from which dataframe (filtered or not) the plot is going to be based on, My problem is that the hover data is not displayed correctly when I use the dropdown button. So i initiate my figure like so:

 first_df = pd.DataFrame({' gene':['gene'+str(i) for i in range(10)], 
                          'x':range(10),'y':range(10),'z':range(10),
                          'columnA':['info A '+str(i) for i in range(10)],
                          'columnB':['info B '+str(i) for i in range(10)]})

second_df = pd.DataFrame({'gene':['gene'+str(i) for i in range(10,20)],
                         'x':range(10,20),'y':range(10,20),'z':range(10,20),
                         'columnA':['info A '+str(i) for i in range(10,20)],
                         'columnB':['info B '+str(i) for i in range(10,20)]})
 first_df_filtered = first_df.iloc[[0,2,4,6,8]]
 second_df_filtered = second_df.iloc[[0,2,4,6,8]]
 
 fig = go.Figure()
 
  fig.add_scatter3d(x = first_df['x'], 
                  y = first_df['y'], 
                  z = first_df['z'],
                  customdata = first_df[['columnA', 'columnB']], 
                  hovertemplate = '<br>'.join(["<b>%{text}</b><br>",
                                               "<i>info on y</i> = %{y:.2f}",
                                               "<i>info on x</i> = %{x:.2f}",
                                               "<i>info customdata 0</i> = %{customdata[0]}", 
                                               "<i>info customdata 1</i> = %{customdata[1]}"
                                              ]),
                  text = first_df['gene'],
                 mode='markers'
                 )
 
 fig.add_scatter3d(x = second_df['x'], 
                 y = second_df['y'], 
                 z = second_df['z'],
                 customdata = second_df[['columnA', 'columnB']], 
                 hovertemplate = "<br>".join(["<b>%{text}</b><br>",
                                              "<i>info on y</i> = %{y:.2f}",
                                              "<i>info on x</i> = %{x:.2f}",
                                              "<i>info customdata 0</i> = %{customdata[0]}", 
                                              "<i>info customdata 1</i> = %{customdata[1]}"
                                             ]),
                 text = second_df['gene'],
                 mode='markers'
                 )
 
 fig.update_layout(updatemenus=[
                                 
                                 #------------------------------------------------------------------
                                 dict(
                                     active=0,
                                     y=0.5,
                                     buttons = list(
                                         [dict(label = 'No filter',
                                               method = 'update',
                                               args = [{'x': [first_df['x'], second_df['x']],
                                                        'y': [first_df['y'], second_df['y']],
                                                        'z': [first_df['z'], second_df['z']],
                                                        'text': [first_df['gene'], second_df['gene']],
                                                        'customdata[0]':[first_df['columnA'], second_df['columnA']],
                                                        'customdata[1]':[first_df['columnB'], second_df['columnB']],
                                                       },
                                                       ]),
                                          dict(label = 'Filter on',
                                               method = 'update',
                                               args = [{'x': [first_df_filtered['x'], second_df_filtered['x']],
                                                        'y': [first_df_filtered['y'], second_df_filtered['y']],
                                                        'z': [first_df_filtered['z'], second_df_filtered['z']],
                                                        'text': [first_df_filtered['gene'], second_df_filtered['gene']],
                                                        'customdata[0]':[first_df_filtered['columnA'], second_df_filtered['columnA']],
                                                        'customdata[1]':[first_df_filtered['columnB'], second_df_filtered['columnB']],
                                                       },
                                                     ]),
                                         ])
                                     ),
     
                     ])

When I click on the button ‘No filter’, all the information shown on the hoverbox for each point is correct, but when I click on the button ‘Filter on’ the information shown in the hoverbox for the customdata is not correct. However if I click again on the ‘No filter’ button the information is correct again. Here is a picture showing an example of my problem:

Does anyone know what I’m doing wrong? Really appreciate it!

Hi,

I believe the problem is in the way you are defining customdata in the update. Plotly sometimes just silently ignore specs that are not correctly formulated, so the updates for everything else work but the customdata is still based on the first array you provided when you first created the traces. I know that because the 4th point in red is 13, but when you exclude odd numbers (your filter) it is 16.

You can try to pass this to customdata (in the update args) instead:

'customdata':[first_df[['columnA', 'columnB']].values, second_df[['columnA', 'columnB']].values]

(and the same for first_df_filtered…)

Your intuition about how to update each “element” of customdata for both traces is correct, I am just not really sure that “customdata[0]” should be interpreted in the way you intended.

Please let me know if this helps! :slight_smile:

1 Like

That worked like a charm thank you so much :blush:

1 Like