I'm using plotly and python 3.9 to display traces on a plot.
My figure have multiple subplots:
fig = make_subplots(rows=numberOfRows, cols=1,
horizontal_spacing = 0.04,
vertical_spacing=0.04,
shared_xaxes=True)
for key, value in filtered_dict.items():
fig.add_trace(go.Scatter(x=eval(data_to_plot_X)[key], y=eval(data_to_plot_Y)[key], hovertemplate=hoverY1,
marker=dict(color=colorList[c]), name=key, legendgroup=key),
row=1, col=1,)
fig.add_trace(go.Scatter(x=eval(data_to_plot_X)[key], y=eval(data_to_plot_Y2)[key], hovertemplate=hoverY2,
marker=dict(color=colorList[c]), name=key, legendgroup=key, showlegend=False),
row=2, col=1,)
fig.update_layout(hovermode="x")
fig.show()
So for each key (corresponding to tests), there is a trace on each subplot and only 1 legend for each key. With the legendgroup, I can activate or deactivate the trace of a key in all subplots in a single click.
Now, I have a lot of keys in my dict, corresponding to multiple groups of tests. I would like it if, with a single click on the legend, I could also deactivate or activate all traces of a group of tests.
But so far I have not managed to succeed, it seems that each trace can only have 1 legend group. Is there a way to achieve that? Thanks
In Plotly, you can only assign a trace to one legendgroup, but you can achieve your goal by using nested legend groups with Plotly buttons. This allows you to group traces by multiple criteria and toggle them collectively.
import plotly.graph_objects as go
from plotly.subplots import make_subplots
data_to_plot_X = {'test1': [1, 2, 3], 'test2': [1, 2, 3], 'test3': [1, 2, 3]}
data_to_plot_Y = {'test1': [2, 4, 6], 'test2': [3, 6, 9], 'test3': [4, 8, 12]}
data_to_plot_Y2 = {'test1': [1, 3, 5], 'test2': [2, 4, 6], 'test3': [3, 5, 7]}
group_dict = {
'group1': ['test1', 'test2'],
'group2': ['test3']
}
colorList = ['blue', 'green', 'red']
fig = make_subplots(rows=2, cols=1, shared_xaxes=True)
c = 0
for key in data_to_plot_X.keys():
fig.add_trace(go.Scatter(
x=data_to_plot_X[key],
y=data_to_plot_Y[key],
hovertemplate='Y1',
marker=dict(color=colorList[c]),
name=key,
legendgroup=key # Control visibility by key across subplots
), row=1, col=1)
fig.add_trace(go.Scatter(
x=data_to_plot_X[key],
y=data_to_plot_Y2[key],
hovertemplate='Y2',
marker=dict(color=colorList[c]),
name=key,
legendgroup=key,
showlegend=False # Hide duplicate legends in the second subplot
), row=2, col=1)
c += 1
buttons = []
for group_name, tests in group_dict.items():
# Create a list of visibility booleans for traces in the group
visibility = []
for key in data_to_plot_X.keys():
if key in tests:
visibility += [True, True] # Show both traces (one for each subplot)
else:
visibility += [False, False] # Hide both traces
buttons.append(dict(label=group_name,
method='update',
args=[{'visible': visibility}]))
# Add buttons to the layout
fig.update_layout(
updatemenus=[dict(
type="buttons",
direction="down",
buttons=buttons,
showactive=True
)],
hovermode="x"
)
fig.show()