I’m looking for a way to have two updatemenu buttons on a plotly figure. One changes the data and the y-axis title and one switches from linear to log scale. Broadly the code below works but I lose something depending on which method I use.
If the buttons
method is update
then when I switch parameters it defaults back to linear scale. If I use restyle
the y-axis title stops updating. Is there a method to only partially update I’ve missed?
import plotly.graph_objects as go
import pandas as pd
def main():
figure = go.Figure()
df = pd.DataFrame([['sample 1', 1, 5, 10],
['sample 2', 2, 20, 200],
],
columns=['sample id', 'param1', 'param2', 'param3']
)
options = ['param1', 'param2', 'param3']
figure.add_trace(go.Bar(x=df['sample id'], y=df[options[0]]))
figure.update_yaxes(title=options[0])
buttons = []
for option in options:
buttons.append({'method': 'restyle', ### this can be update or restyle, each has different issues
'label': option,
'args': [{'y': [df[option]],
'name': [option]},
{'yaxis': {'title': option}},
[0]]
})
scale_buttons = [{'method': 'relayout',
'label': 'Linear Scale',
'args': [{'yaxis': {'type': 'linear'}}]
},
{'method': 'relayout',
'label': 'Log Scale',
'args': [{'yaxis': {'type': 'log'}}]
}
]
figure.update_layout(yaxis_title=options[0],
updatemenus=[dict(buttons=buttons,
direction='down',
x=0,
xanchor='left',
y=1.2,
),
dict(buttons=scale_buttons,
direction='down',
x=1,
xanchor='right',
y=1.2,
)],
)
figure.show()
if __name__ == '__main__':
main()
You need to use the update
method for the first dropdown (restyle
only updates data, update
updates both data and layout).
Now to fix the issue, the key is to use 'yaxis.title': option
instead of 'yaxis': {'title': option}
in the arguments, otherwise the update will reset the yaxis params other than title
to their defaults (same applies for the yaxis type
) :
buttons = []
for option in options:
buttons.append({
'method': 'update',
'label': option,
'args': [{
'y': [df[option]],
'name': [option]
}, {
'yaxis.title': option
}]
})
scale_buttons = [{
'method': 'relayout',
'label': 'Linear Scale',
'args': [{'yaxis.type': 'linear'}],
}, {
'method': 'relayout',
'label': 'Log Scale',
'args': [{'yaxis.type': 'log'}]
}]