Yeah,
better split per year.
I have tried to your last scenario, if you still interested, please take a look :
import plotly.express as px
import pandas as pd
from datetime import datetime
df = px.data.tips()
df['date'] = df.day
df = df.replace({'date': {'Thur': datetime(2000,1,1),'Fri': datetime(2001,1,1),'Sat': datetime(2002,1,1),'Sun': datetime(2003,1,1)}})
# This example to make sure there are 3 columns like your post description
# column `date` is like Date
# column `total_bill`` is act like SPY (ticker) Daily % change
# column `tip` is act like QQQ Daily % change
df = df[["total_bill","tip","date"]]
# create new column year only
df['year'] = df.date.dt.year
# change column name if needed
df.columns=["SPY","QQQ","date","year"]
# ignore date
df = df[["SPY","QQQ","year"]]
# indices list
indices = ["SPY","QQQ"]
# melt data all indices
df = pd.melt(df, id_vars=['year'], value_vars=indices)
# chang columns
df.columns = ["year","index_symbol","value"]
# year
years = df.year.unique().tolist()
titles = []
xaxis_titles=[]
# create histogram based on how many combination that may be possible
for year in years:
df_year = df[df['year']==year]
if titles:
fig_temp = px.histogram(df_year, x="value", color="index_symbol")
fig.add_traces(fig_temp.data)
else:
fig = px.histogram(df_year, x="value", color="index_symbol")
titles += [year]
xaxis_titles += ['']
print(len(fig.data))
# create function to return list of visible plot
def get_visible(idx):
visibles = [False] * len(fig.data)
for vis_idx in range(idx*len(indices),idx*len(indices)+len(indices)) :
visibles[vis_idx] = True
return visibles
# at initial hide all plots except first year
fig.update_traces(dict(visible=False))
for vis_idx in range(0, len(indices)):
fig.data[vis_idx].visible=True
# buttons dropdown
buttons = [ dict(label=titles[idx],method="update",args=[{"visible": get_visible(idx)},{"title": titles[idx],"xaxis": {"title":xaxis_titles[idx]}}]) for idx,data in enumerate(years)]
# create dropdown menu
fig.update_layout(
updatemenus=[
dict(
active=0, # set the first label as seleceted plot
buttons=list(buttons),
)
])
# Set first title and first xaxis title for initial display
fig.update_layout(title_text=titles[0],xaxis=dict(title=xaxis_titles[0]))
fig.show()