Question: I'm new to Python, Pandas and Plotly so maybe the answer is easy but I couldn't find anything on the forum or anywhere else … I don’t want to use Dash nor ipywidgets since I want to be able to export in HTML using plotly.offline.plot (I need an interactive HTML file to dynamically control the figure without any server running like Dash seems to do). Well my problem is that I would like to filter a plotly figure using several (cumulative) dropdown buttons (2 in this example, but it could be more) by filtering the original data with the selected value in the dropdown lists. num label color value 1 A red 0.4 2 A blue 0.2 3 A green 0.3 4 A red 0.6 5 A blue 0.7 6 A green 0.4 7 B blue 0.2 8 B green 0.4 9 B red 0.4 10 B green 0.2 11 C red 0.1 12 C blue 0.3 13 D red 0.8 14 D blue 0.4 15 D green 0.6 16 D yellow 0.5  In this example, if I choose label ‘A’ and color ‘red’ I would like to display ONLY the values of rows with label ‘A’ AND color ‘red’, as follow : num label color value 1 A red 0.4 4 A red 0.6  Then, the figure should display only 2 values 1) So here is the code I have for the moment (see below) but I don’t know how to continue. Do you have any idea ? 2) Extra question : is it possible to use checkboxes instead of dropdown lists, to be able to select multiple values inside a criteria, for example : Labels filter could be A or B, not only one in the list … Thanks in advance for your help ! import pandas as pd import plotly.graph_objects as go d = { 'num' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], 'label' : ['A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'D', 'D', 'D', 'D'], 'color' : ['red', 'blue', 'green', 'red', 'blue', 'green', 'blue', 'green', 'red', 'green', 'red', 'blue', 'red', 'blue', 'green', 'yellow'], 'value' : [0.4, 0.2, 0.3, 0.6, 0.7, 0.4, 0.2, 0.4, 0.4, 0.2, 0.1, 0.3, 0.8, 0.4, 0.6, 0.5] } # Build dataframe df = pd.DataFrame(data=d) # Build dropdown Labels labels = df["label"].unique() buttonsLabels = [dict(label = "All labels", method = "restyle", args = [{'y' : [df["value"] * 100]}] # or what else ? )] for label in labels: buttonsLabels.append(dict(label = label, method = "restyle", visible = True, #args = [{'y' : ??? }] )) # Build dropdown Colors colors = df["color"].unique() buttonsColors = [dict(label = "All colors", method = "restyle", args = [{'y' : [df["value"] * 100]}] # or what else ? )] for color in colors: buttonsColors.append(dict(label = color, method = "restyle", visible = True, # args = [{'y' : ??? }] )) # Display figure fig = go.Figure(data = [ go.Scatter(x = df["num"], y = df["value"] * 100 ) ]) fig.update_layout(updatemenus = [ dict(buttons = buttonsLabels, showactive = True), dict(buttons = buttonsColors, showactive = True, y = 0.8) ]) fig.show() 

Answer: It's certainly possible to display and filter a dataframe with multiple dropdowns. The code snippet below will do exactly that for you. The snippet has quite a few elements in common with your provided code, but I had to build it from scratch to make sure everything harmonized. Run the snippet below, and select A and Red to see that you will in fact get: num label color value 1 A red 0.4 4 A red 0.6  Plot:  There's still room for improvement. I'll polish the code and improve the layout when I find the time. First, please let me know if this is in fact what you were looking for. Complete code: # Imports import plotly.graph_objs as go import pandas as pd import numpy as np # source data df = pd.DataFrame({0: {'num': 1, 'label': 'A', 'color': 'red', 'value': 0.4}, 1: {'num': 2, 'label': 'A', 'color': 'blue', 'value': 0.2}, 2: {'num': 3, 'label': 'A', 'color': 'green', 'value': 0.3}, 3: {'num': 4, 'label': 'A', 'color': 'red', 'value': 0.6}, 4: {'num': 5, 'label': 'A', 'color': 'blue', 'value': 0.7}, 5: {'num': 6, 'label': 'A', 'color': 'green', 'value': 0.4}, 6: {'num': 7, 'label': 'B', 'color': 'blue', 'value': 0.2}, 7: {'num': 8, 'label': 'B', 'color': 'green', 'value': 0.4}, 8: {'num': 9, 'label': 'B', 'color': 'red', 'value': 0.4}, 9: {'num': 10, 'label': 'B', 'color': 'green', 'value': 0.2}, 10: {'num': 11, 'label': 'C', 'color': 'red', 'value': 0.1}, 11: {'num': 12, 'label': 'C', 'color': 'blue', 'value': 0.3}, 12: {'num': 13, 'label': 'D', 'color': 'red', 'value': 0.8}, 13: {'num': 14, 'label': 'D', 'color': 'blue', 'value': 0.4}, 14: {'num': 15, 'label': 'D', 'color': 'green', 'value': 0.6}, 15: {'num': 16, 'label': 'D', 'color': 'yellow', 'value': 0.5}, 16: {'num': 17, 'label': 'E', 'color': 'purple', 'value': 0.68}} ).T df_input = df.copy() # split df by labels labels = df['label'].unique().tolist() dates = df['num'].unique().tolist() # dataframe collection grouped by labels dfs = {} for label in labels: dfs[label]=pd.pivot_table(df[df['label']==label], values='value', index=['num'], columns=['color'], aggfunc=np.sum) # find row and column unions common_cols = [] common_rows = [] for df in dfs.keys(): common_cols = sorted(list(set().union(common_cols,list(dfs[df])))) common_rows = sorted(list(set().union(common_rows,list(dfs[df].index)))) # find dimensionally common dataframe df_common = pd.DataFrame(np.nan, index=common_rows, columns=common_cols) # reshape each dfs[df] into common dimensions dfc={} for df_item in dfs: #print(dfs[unshaped]) df1 = dfs[df_item].copy() s=df_common.combine_first(df1) df_reshaped = df1.reindex_like(s) dfc[df_item]=df_reshaped # plotly start fig = go.Figure() # one trace for each column per dataframe: AI and RANDOM for col in common_cols: fig.add_trace(go.Scatter(x=dates, visible=True, marker=dict(size=12, line=dict(width=2)), marker_symbol = 'diamond',name=col ) ) # menu setup updatemenu= [] # buttons for menu 1, names buttons=[] # create traces for each color: # build argVals for buttons and create buttons for df in dfc.keys(): argList = [] for col in dfc[df]: #print(dfc[df][col].values) argList.append(dfc[df][col].values) argVals = [ {'y':argList}] buttons.append(dict(method='update', label=df, visible=True, args=argVals)) # buttons for menu 2, colors b2_labels = common_cols # matrix to feed all visible arguments for all traces # so that they can be shown or hidden by choice b2_show = [list(b) for b in [e==1 for e in np.eye(len(b2_labels))]] buttons2=[] buttons2.append({'method': 'update', 'label': 'All', 'args': [{'visible': [True]*len(common_cols)}]}) # create buttons to show or hide for i in range(0, len(b2_labels)): buttons2.append(dict(method='update', label=b2_labels[i], args=[{'visible':b2_show[i]}] ) ) # add option for button two to hide all buttons2.append(dict(method='update', label='None', args=[{'visible':[False]*len(common_cols)}] ) ) # some adjustments to the updatemenus updatemenu=[] your_menu=dict() updatemenu.append(your_menu) your_menu2=dict() updatemenu.append(your_menu2) updatemenu[1] updatemenu[0]['buttons']=buttons updatemenu[0]['direction']='down' updatemenu[0]['showactive']=True updatemenu[1]['buttons']=buttons2 updatemenu[1]['y']=0.6 fig.update_layout(showlegend=False, updatemenus=updatemenu) fig.update_layout(yaxis=dict(range=[0,df_input['value'].max()+0.4])) # title fig.update_layout( title=dict( text= "<i>Filtering with multiple dropdown buttons</i>", font={'size':18}, y=0.9, x=0.5, xanchor= 'center', yanchor= 'top')) # button annotations fig.update_layout( annotations=[ dict(text="<i>Label</i>", x=-0.2, xref="paper", y=1.1, yref="paper", align="left", showarrow=False, font = dict(size=16, color = 'steelblue')), dict(text="<i>Color</i>", x=-0.2, xref="paper", y=0.7, yref="paper", align="left", showarrow=False, font = dict(size=16, color = 'steelblue') ) ]) fig.show()