I am plotting chart using below code:
fig = px.line(df, x='Time', y=['one','two'], color= df.index)
fig['layout']['xaxis']['autorange'] = "reversed"
fig.update_layout(legend_title="Price")
fig.show()
Dataframe i am working with like is below:
Time one two
100 9:30 129 243
110 10:30 234 453
120 11:00 155 234
Want to add dropdown menu to select from index and show one row at a time in chart.
example if i select 110 from drop down it should only show chart for that row.
Is there any easy fix for it.
Thank you in adavance.
Here's my solution:
In order to set the proper options for the dropdown menu, it would be helpful to have a function that creates the list of options (shown below)
# Create proper buttons list
def makeButtonsList(idxs):
buttons = []
for i, idx in enumerate(idxs):
visibleArr = np.full((2*df.index.shape[0],),
False, dtype=bool) # 2x number of booleans since one/two vals are separate plots
visibleArr[2*i] = True # Set two booleans next to each other (representing one & two) to true
visibleArr[(2*i)+1] = True
buttons.append(dict(label=str(idx),
method='update',
args=[{'visible': list(visibleArr)}])) # 'Visible' arg determines which plots are shown
# depending on which dropdown is selected
return buttons
Next create the traces for the data (with your sample data, I created a bar chart but you could easily modify this)
traces = []
for i in range(df.Time.shape[0]):
rowData = df.iloc[i, :]
time = rowData.Time
one = rowData.one
two = rowData.two
traces.append(go.Bar(x=[time], y=[one], name='One'))
traces.append(go.Bar(x=[time], y=[two], name='Two'))
where df is the dataframe you are working with.
Finally put it all together and create the Plotly plot!
# Import packages
import pandas as pd
import numpy as np
import plotly.graph_objs as go
import plotly.express as px
# Create proper buttons list
def makeButtonsList(idxs):
buttons = []
for i, idx in enumerate(idxs):
visibleArr = np.full((2*df.index.shape[0],),
False, dtype=bool) # 2x number of booleans since one/two vals are separate plots
visibleArr[2*i] = True # Set two booleans next to each other (representing one & two) to true
visibleArr[(2*i)+1] = True
buttons.append(dict(label=str(idx),
method='update',
args=[{'visible': list(visibleArr)}])) # 'Visible' arg determines which plots are shown
# depending on which dropdown is selected
return buttons
# Create traces
traces = []
for i in range(df.Time.shape[0]):
rowData = df.iloc[i, :]
time = rowData.Time
one = rowData.one
two = rowData.two
traces.append(go.Bar(x=[time], y=[one], name='One'))
traces.append(go.Bar(x=[time], y=[two], name='Two'))
# Create figure
fig = go.Figure(data=traces)
# Add dropdown options
fig.update_layout(
updatemenus=[
dict(
buttons=makeButtonsList(df.index),
direction="down",
pad={"r": 10, "t": 10},
showactive=True,
x=0.55,
xanchor="left",
y=1.2,
yanchor="top"
),
]
)
# Add annotation for index selected
fig.update_layout(
annotations=[
dict(text="Index:", showarrow=False,
x=0, y=1.15, yref="paper", align="left")
],
xaxis_title = 'Time',
yaxis_title = 'Value',
)
# Show the plot
fig.show()
Here is a sample plot:
BONUS:
If you think this method is tedious, and a slider bar would do the job just fine, Plotly supports animation of bar charts. Here is the following code you could use:
fig = px.bar(df, x='Time', y=['one','two'], animation_frame=df.index)
fig.update_layout(title='Data', barmode='group')
fig.show()
Here is the resulting plot:
Related
I am trying to make a function using plotly 5.9.0 that will reproduce a specific type of plot. I am having trouble aligning legend entries with their subplots, especially when the figure is resizable.
This is what i currently have:
import pandas as pd
import numpy as np
import plotly.graph_objects as go
import plotly.subplots as sp
from plotly.offline import plot
def get_df(len_df):
x = np.linspace(-1, 1, len_df)
# Create a dictionary with the functions to use for each column
funcs = {
"column1": np.sin,
"column2": np.cos,
"column3": np.tan,
"column4": np.arcsin,
"column5": np.arccos,
"column6": np.arctan
}
# Create an empty dataframe with the same index as x
df = pd.DataFrame(index=pd.date_range('2022-01-01', periods=len(x), freq='H'))
# Populate the dataframe with the functions
for column, func in funcs.items():
df[column] = func(x)
return df
def plot_subplots(df, column_groups, fig_height=1000):
# Create a figure with a grid of subplots
fig = sp.make_subplots(rows=len(column_groups), shared_xaxes=True, shared_yaxes=True, vertical_spacing=.1)
# Iterate over the list of column groups
for i, group in enumerate(column_groups):
# Iterate over the columns in the current group
for column in group:
# Add a scatter plot for the current column to the figure, specifying the row number
fig.add_trace(go.Scatter(x=df.index, y=df[column], mode="lines", name=column, legendgroup=str(i)), row=i + 1, col=1)
fig.update_layout(legend_tracegroupgap=fig_height/len(column_groups), height=fig_height)
return fig
df = get_df(1000)
column_groups = [
['column1', 'column3'],
['column2', 'column4'],
['column5', 'column6']
]
fig = plot_subplots(df, column_groups)
plot(fig)
This produces a plot that looks like this:
How do I align my legend subgroups with the top of each corresponding plotly subplot?
If we can somehow relate the legend_tracegroupgap to the height of the figure that would be a great first step. This feels like such a logical thing to want that I feel like I'm missing something.
In reply to r-beginners:
I tried this:
tracegroupgap=(fig.layout.yaxis.domain[1] - fig.layout.yaxis.domain[0])*fig_height
Which works perfectly for a figure with a height of 1000. But not for a height of 500 pixels. I still have to subtract some value that has to do with the vertical spacing is my guess.
There are few functions in plotly that allow strict size definitions other than figure size. The position of the legend in a subplot can also only be set by setting the spacing between legend groups as a pixel value (the default is 10px). So I used a function provided for development to check the area of the subplot.
dev_fig = fig.full_figure_for_development()
'yxais':{
...
domain': [0.7333333333333334, 1],
...
}
'yaxis2': {
...
'domain': [0.3666666666666667, 0.6333333333333333],
...
}
'yaxis3': {
...
'domain': [0, 0.26666666666666666],
...
}
fig.update_layout(legend_tracegroupgap=266, height=fig_height)
Since each subplot is drawn to the nearest 0.26 units, the gap was set at 266. However, this does not mean that we have derived a perfect value. I am sure other factors are still affecting this, and I hope to get answers from actual developers and others.
Question has been updated so that if the height of the graph is 500px
The default margins are 100px top and 80px bottom, so set them to 0.
def plot_subplots(df, column_groups, fig_height=500):
# Create a figure with a grid of subplots
fig = sp.make_subplots(rows=len(column_groups), shared_xaxes=True, shared_yaxes=True, vertical_spacing=.1)
# Iterate over the list of column groups
for i, group in enumerate(column_groups):
# Iterate over the columns in the current group
for column in group:
# Add a scatter plot for the current column to the figure, specifying the row number
fig.add_trace(go.Scatter(x=df.index, y=df[column], mode="lines", name=column, legendgroup=str(i)), row=i + 1, col=1)
tracegroupgap = (fig.layout.yaxis.domain[1] - fig.layout.yaxis.domain[0])*fig_height
print(fig.layout.yaxis.domain[0], fig.layout.yaxis.domain[1])
print(tracegroupgap)
fig.update_layout(margin=dict(t=0,b=0,l=0,r=0))
fig.update_layout(legend_tracegroupgap=tracegroupgap, height=fig_height)#fig_height/len(column_groups)
return fig
This question already has answers here:
Plotly: How to filter a pandas dataframe using a dropdown menu?
(1 answer)
Plotly: How to display and filter a dataframe with multiple dropdowns?
(1 answer)
Closed 2 years ago.
I am new to Plotly and fascinated by its interactive features. I have three pandas dataframes of electricity generation mix of three countries, which looks like this:
I have been able to create an interactive bar chart using Plotly for electricity generation mix based on df1 using
import plotly.express as px
fig=px.bar(df1, title="Electricity generation mix of Germany in TWh (2000-2019)", color_discrete_sequence=colors)
fig
I intend to add a button or dropdown to this bar chart, where I can select countries based on each data frame (df1,df2 and df3). What would be the best approach to do it? Should I rather have the data of all three countries in one dataframe?
The easiest way to do this is to use the graph objects library and iterate through your data with the "add_trace" method of a Plotly figure.
import pandas as pd
import plotly.graph_objects as go
#Dummy data
df_germany = pd.DataFrame({'Fuels':[2010,2011],'Coal':[200,250],'Gas':[400,500]})
df_poland = pd.DataFrame({'Fuels':[2010,2011],'Coal':[500,150],'Gas':[600,100]})
df_spain = pd.DataFrame({'Fuels':[2010,2011],'Coal':[700,260],'Gas':[900,400]})
#put dataframes into object for easy access:
df_dict = {'Germany': df_germany,
'Poland': df_poland,
'Spain': df_spain}
#create a figure from the graph objects (not plotly express) library
fig = go.Figure()
buttons = []
i = 0
#iterate through dataframes in dict
for country, df in df_dict.items():
#iterate through columns in dataframe (not including the year column)
for column in df.drop(columns=['Fuels']):
#add a bar trace to the figure for the country we are on
fig.add_trace(go.Bar(
name = column,
#x axis is "fuels" where dates are stored as per example
x = df.Fuels.to_list(),
#y axis is the data for the column we are on
y = df[column].to_list(),
#setting only the first country to be visible as default
visible = (i==0)
)
)
#args is a list of booleans that tells the buttons which trace to show on click
args = [False] * len(df_dict)
args[i] = True
#create a button object for the country we are on
button = dict(label = country,
method = "update",
args=[{"visible": args}])
#add the button to our list of buttons
buttons.append(button)
#i is an iterable used to tell our "args" list which value to set to True
i+=1
fig.update_layout(
updatemenus=[
dict(
#change this to "buttons" for individual buttons
type="dropdown",
#this can be "left" or "right" as you like
direction="down",
#(1,1) refers to the top right corner of the plot
x = 1,
y = 1,
#the list of buttons we created earlier
buttons = buttons)
],
#stacked bar chart specified here
barmode = "stack",
#so the x axis increments once per year
xaxis = dict(dtick = 1))
fig.show()
Should yield:
I'm using python and creating standalone html files with interactive plots (no Dash). I have been able to build a plotly plot with buttons that can toggle the visibility of traces in the plot. However, this functionality removes the traces from the legend as well. What I would like is to be able to keep the functionality of the legend (click a single trace to toggle visibility) but also have a set of buttons that extends that functionality to a group of traces that I define.
The goal is to be able toggle everything (or a select group) to invisible but add individual items from that group back to visible as needed.
Below is an example (using modified code from this answer by vestland) to show what I am currently attempting.
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import datetime
# mimic OP's datasample
NPERIODS = 200
np.random.seed(123)
df = pd.DataFrame(np.random.randint(-10, 12, size=(NPERIODS, 4)),
columns=list('ABCD'))
datelist = pd.date_range(datetime.datetime(2020, 1, 1).strftime('%Y-%m-%d'),
periods=NPERIODS).tolist()
df['dates'] = datelist
df = df.set_index(['dates'])
df.index = pd.to_datetime(df.index)
df.iloc[0] = 0
df = df.cumsum()
# set up multiple traces
traces = []
buttons = []
for col in df.columns:
traces.append(go.Scatter(x=df.index,
y=df[col],
visible=True,
name=col)
)
buttons.append(dict(method='update',
label=col,
visible=True,
args=[{'visible':[x == col for x in df.columns]}],
args2=[{'visible':[x != col for x in df.columns]}]
)
)
# create the layout
layout = go.Layout(
updatemenus=[
dict(
type='buttons',
direction='right',
x=0.7,
y=1.3,
showactive=True,
buttons=buttons
)
],
title=dict(text='Toggle Traces',x=0.5),
showlegend=True
)
fig = go.Figure(data=traces,layout=layout)
# add dropdown menus to the figure
fig.show()
That example does not work how I would like. Below is a screenshot of what it looks like at first.
The problem is that if I use one of those buttons, it does hide all the other traces but it also removes them from the legend so they can't be toggled back to visible.
So my question becomes, is there a different value in the args list/dictionary that can be given for the functionality to match that of simply clicking a trace in the legend?
Sort of related, is there some way to get the current state of visibility for each trace?
In order to make it possible to toggle any trace on and off without affecting the others, it seems you'll have to include one updatemenu per button. There might be other ways to do it, but the code snippet below will produce the following plot:
Plot 1 - At launch all are selected
Plot 2 - C and D toggled off
Plot 3 - All off
Plot 4 - All on
Complete code:
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import datetime
import plotly.express as px
periods = 200
cols = list('ABCD')
np.random.seed(123)
df = pd.DataFrame(np.random.randint(-10, 12, size=(periods, len(cols))),
columns=cols)
datelist = pd.date_range(datetime.datetime(2020, 1, 1).strftime('%Y-%m-%d'),
periods=periods).tolist()
df['dates'] = datelist
df = df.set_index(['dates'])
df.index = pd.to_datetime(df.index)
df.iloc[0] = 0
df = df.cumsum()
# # plotly
fig = go.Figure()
colors = px.colors.qualitative.Plotly
# set up multiple traces
for col in df.columns:
fig.add_trace(go.Scatter(x=df.index,
y=df[col],
name = col,
visible=True
)
)
um = [ {} for _ in range(len(df.columns)) ]
buttons = []
menuadjustment = 0.15
buttonX = -0.1
buttonY = 1 + menuadjustment
for i, col in enumerate(df.columns):
button = dict(method='restyle',
label=col,
visible=True,
args=[{'visible':True,
'line.color' : colors[i]}, [i]],
args2 = [{'visible': False,
'line.color' : colors[i]}, [i]],
)
# adjust some button features
buttonY = buttonY-menuadjustment
um[i]['buttons'] = [button]
um[i]['showactive'] = False
um[i]['y'] = buttonY
um[i]['x'] = buttonX
# add a button to toggle all traces on and off
button2 = dict(method='restyle',
label='All',
visible=True,
args=[{'visible':True}],
args2 = [{'visible': False}],
)
# assign button2 to an updatemenu and make some adjustments
um.append(dict())
um[i+1]['buttons'] = [button2]
um[i+1]['showactive'] = True
um[i+1]['y']=buttonY - menuadjustment
um[i+1]['x'] = buttonX
# add dropdown menus to the figure
fig.update_layout(showlegend=True, updatemenus=um)
# adjust button type
for m in fig.layout.updatemenus:
m['type'] = 'buttons'
f = fig.full_figure_for_development(warn=False)
fig.show()
After a decent bit of searching, I have been able to figure it out thanks to this answer on the Plotly forum. I have not been able to find somewhere that lists all of these options yet, but that would be very helpful.
It appears that the list given to 'visible' in the args dictionary does not need to be only booleans. In order to keep the items visible in the legend but hidden in the plot, you need to set the values to 'legendonly'. The legend entries can then still be clicked to toggle individual visibility. That answers the main thrust of my question.
args = [{'visible': True}]
args = [{'visible': 'legendonly'}]
args = [{'visible': False}]
Vestland's answer helped solve the second part of my question, only modifying the traces I want and leaving everything else the same. It turns out that you can pass a list of indices after the dictionary to args and those args will only apply to the traces at the indices provided. I used list comprehension in the example to find the traces that match the given name. I also added another trace for each column to show how this works for multiple traces.
args = [{'key':arg}, [list of trace indices to apply key:arg to]]
Below is the now working code.
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import datetime
# mimic OP's datasample
NPERIODS = 200
np.random.seed(123)
df = pd.DataFrame(np.random.randint(-10, 12, size=(NPERIODS, 4)),
columns=list('ABCD'))
datelist = pd.date_range(datetime.datetime(2020, 1, 1).strftime('%Y-%m-%d'),
periods=NPERIODS).tolist()
df['dates'] = datelist
df = df.set_index(['dates'])
df.index = pd.to_datetime(df.index)
df.iloc[0] = 0
df = df.cumsum()
# set up multiple traces
traces = []
buttons = []
for col in df.columns:
traces.append(go.Scatter(x=df.index,
y=df[col],
visible=True,
name=col)
)
traces.append(go.Scatter(x=df.index,
y=df[col]+20,
visible=True,
name=col)
)
buttons.append(dict(method='restyle',
label=col,
visible=True,
args=[{'visible':True},[i for i,x in enumerate(traces) if x.name == col]],
args2=[{'visible':'legendonly'},[i for i,x in enumerate(traces) if x.name == col]]
)
)
allButton = [
dict(
method='restyle',
label=col,
visible=True,
args=[{'visible':True}],
args2=[{'visible':'legendonly'}]
)
]
# create the layout
layout = go.Layout(
updatemenus=[
dict(
type='buttons',
direction='right',
x=0.7,
y=1.3,
showactive=True,
buttons=allButton + buttons
)
],
title=dict(text='Toggle Traces',x=0.5),
showlegend=True
)
fig = go.Figure(data=traces,layout=layout)
# add dropdown menus to the figure
fig.show()
This gives the following functionality:
the "All" button can toggle visibility of all traces.
Each other button will only toggle the traces with the matching name. Those traces will still be visible in the legend and can be turned back to visible by clicking on them in the legend or clicking the button again.
After clicking the "B" button (twice to hit arg2).
And then after clicking the first B trace in the legend.
I have a drop down menu in plotly to display all graphs for every state in the country. I also have a graph that shows the whole US.
In my drop down menu I want to move the US to the top of the display and not in the alphabetical order.
Any suggestions? Really stuck and reorganizing the data frame doesn't work.
state_names = summary['state'].unique()
state_names.sort()
age_groups = summary['age_group'].unique()
x = summary['ca_monthly'].unique()
data_list = []
for state in state_names:
state_list = []
state_data = summary[summary['state']==state]
for age in age_groups:
state_list.append(
state_data[state_data['age_group']==age]['poverty_rate'])
data_list.append(state_list)
data = pd.DataFrame(data_list, columns=age_groups)
data['State'] = state_names
data = data.set_index('State')
fig = go.Figure()
legend_names = {'child': 'Child poverty',
'adult': 'Adult poverty',
'all': 'Overall poverty'}
default = state_names[0]
for age in age_groups:
fig.add_trace(go.Scatter(
x=x,
y=data[age][default],
name=legend_names[age]
))
buttons = []
title = 'Poverty impact of a child allowance in '
for state in state_names:
new_button = {'method': 'update',
'label': state,
'args': [{'y': data.loc[state]},
{'title.text': title + state}]}
buttons.append(new_button)
# construct menus
updatemenus = [{'buttons': buttons,
'direction': 'down',
'showactive': True,}]
# update layout with buttons, and show the figure
fig.update_layout(updatemenus=updatemenus)
fig.update_layout(
title= title + default,
xaxis_title='Monthly Child Allowance',
yaxis_title='SPM poverty rate',
yaxis_ticksuffix='%',
font=dict(family='Roboto'),
hovermode='x',
xaxis_tickprefix='$',
xaxis_ticksuffix='',
plot_bgcolor='white',
legend_title_text='',
legend=dict(yanchor='top', y=0.99, xanchor='right', x=0.99),
xaxis=dict(tickmode='linear', dtick = 50),
yaxis=dict(range=[0, summary.poverty_rate.max() * 1.05], dtick=2)
)
fig.update_traces(mode='markers+lines', hovertemplate=None,
marker=dict(size=4))
fig.show(config={'displayModeBar': False})
The answer:
Just add the buttons to the dropdown menu and each corresponding subset of your data to the button args in whatever order you prefer.
The details:
Regarding:
[...] reorganizing the data frame doesn't work.
Yes it would. But you don't have to. We seem to be talking about dropdown menus here. So just add the buttons in whatever order you'd like.
How it all turns out will depend entirely on your dataset and what you would in fact like to display. But you've not provided the former nor described the latter in full detail. But since you're using functions such as state_names = summary['state'].unique() I'm going to assume that your dataset is of a long format.
I'm also going to assume that you're only displaying one trace at a time here. Or else this approach wouldn't make much sense since you would obtain the very same functionality with the interactivity of plotlys default legend functionality.
I'll use the px.data.gapminder() dataset where running dfi['continent'].unique().tolist() will give ['Asia', 'Europe', 'Africa', 'Americas', 'Oceania']. I'm also going to throw in some aggregated data for the entire world, and define the order of the buttons to be ['World', 'Africa', 'Americas', 'Asia', 'Europe', 'Oceania'.
I hope this will reflect the structure of your real world data. And if it doesn't, then I strongly suggest that you take the time to learn how to efficiently build and share a pandas dataframe. The dataset also contains observations for individual countries. You'll just have to pretend that the world is USA and that the countries are states. But I suspect that won't be a problem.
Following the logic I've just described, the code snippet below will produce the following plot, with world defined to be placed at the top, and with the individual continents following in alphabetical order.
Complete code:
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
# dataframe, input
dfi = px.data.gapminder()
# dataframe, aggregated by continent
dfc = dfi.groupby( [ "continent", "year"] ).mean().reset_index()
# dataframe with calculated mean for all continents
dfw = dfc.groupby( ["year"] ).mean().reset_index()
dfw['continent']='World'
dfw = dfw.append(dfc)
dfw
# select a category (world),
# take it out of the categories,
# put it first in a list,
# and add the rest of the categories alphabetically
mainGeo = dfw['continent'].unique().tolist()
mainGeo
mainCat = 'World'
mainGeo.remove(mainCat)
mainGeo.sort()
order = [mainCat] + mainGeo
order
colors = px.colors.qualitative.Plotly
# plotly figure setup
fig=go.Figure()
fig.add_traces(go.Scatter(x=df['year'], y = df['lifeExp'], name=geo,
mode='lines', line=dict(color = colors[2], width = 1))
)
# dropdown menu
updatemenu = []
buttons = []
# button with one option for each dataframe
for geo in order:
buttons.append(dict(method='restyle',
label=geo,
visible=True,
args=[{'y':[dfw[dfw['continent']==geo]['lifeExp'].values],
'x':[dfw[dfw['continent']==geo]['year'].values],
'type':'scatter'}, ],
)
)
# some adjustments to the updatemenus
updatemenu = []
your_menu = dict()
updatemenu.append(your_menu)
updatemenu[0]['buttons'] = buttons
updatemenu[0]['direction'] = 'down'
updatemenu[0]['showactive'] = True
# add dropdown menus to the figure
fig.update_layout(showlegend=False, updatemenus=updatemenu)
fig.show()
I have made a graph using time axis on the X axis, however I want to show only today's data. (i.e restrict the date to current date)
Here is the code I used to produce those graphs :
fig = go.Figure()
fig = make_subplots(rows=2,cols=1,shared_xaxes=True,vertical_spacing=0.02)
fig.add_trace(go.Scatter(x=data['time'],y=data['x_last_recorded'],name='xyz',mode='lines+markers'),row=2,col=1)
fig.add_trace(go.Scatter(x=predict_data['time'],y=predict_data['x1_last_recorded'],name='x1yz',mode='lines'),row=2,col=1)
fig.update_layout(height=800,width=1500,title='first_graph',yaxis_title='Values')
This has got me a graph of how I want, but it is showing all the dates present in the dataframe. How do I fetch only the current date's data?
Structure of time : dd-mm-yyyy hh:mm
We can solve your challenge by subsetting your dataframe using an approach such as df_current = df[df.index.date==df.index.date[-1]], and then restyle your figure by letting different subsets be represented by different options in a dropdown menu.
Here's the resulting figure for the different subsets / selection options:
All dates
Current date
Complete code:
# imports
import plotly.graph_objects as go
import pandas as pd
import numpy as np
# sample data in the form of an hourlt
np.random.seed(1234)
tseries = pd.date_range("01.01.2020", "01.04.2020", freq="H")
data = np.random.randint(-10, 12, size=(len(tseries), 2))
df = pd.DataFrame(index=tseries, data=data)
df.drop(df.tail(1).index,inplace=True)
df.columns=list('AB')
df.iloc[0]=0
df=df.cumsum()
# subset method
df_current = df[df.index.date==df.index.date[-1]]
# plotly setup
fig = go.Figure()
# set up a trace for each column in a dataframe
for col in df.columns:
fig.add_trace(go.Scatter(x=df.index, y =df[col], name=col))
# container for updatemenus and buttons
updatemenu = []
buttons = []
# button 1
buttons.append(dict(method='restyle',
label='All',
visible=True,
args=[{'y':[df[col].values for col in df.columns],
'x':[df.index],
'type':'scatter'}, ],))
# button 2
buttons.append(dict(method='restyle',
label='Current',
visible=True,
args=[{'y':[df_current[col].values for col in df_current.columns],
'x':[df_current.index],
'type':'scatter'}, ],))
# menu setup
your_menu = dict()
updatemenu.append(your_menu)
updatemenu.append(your_menu)
updatemenu[0]['buttons'] = buttons
updatemenu[0]['direction'] = 'down'
updatemenu[0]['showactive'] = True
# add dropdown menus to the figure
fig.update_layout(showlegend=False, updatemenus=updatemenu)
fig.show()