I am recently exploring Plotly and I wonder if there is a way for sharing a plot and let the viewer switch between a logarithmic axis and linear axis.
Any suggestion?
Plotly has a dropdown feature which allows the user to dynamically update the plot styling and/or the traces being displayed. Below is a minimal working example of a plot where the user can switch between a logarithmic and linear scale.
import plotly
import plotly.graph_objs as go
x = [1, 2, 3]
y = [1000, 10000, 100000]
y2 = [5000, 10000, 90000]
trace1 = go.Bar(x=x, y=y, name='trace1')
trace2 = go.Bar(x=x, y=y2, name='trace2', visible=False)
data = [trace1, trace2]
updatemenus = list([
dict(active=1,
buttons=list([
dict(label='Log Scale',
method='update',
args=[{'visible': [True, True]},
{'title': 'Log scale',
'yaxis': {'type': 'log'}}]),
dict(label='Linear Scale',
method='update',
args=[{'visible': [True, False]},
{'title': 'Linear scale',
'yaxis': {'type': 'linear'}}])
]),
)
])
layout = dict(updatemenus=updatemenus, title='Linear scale')
fig = go.Figure(data=data, layout=layout)
plotly.offline.iplot(fig)
I added two traces to the data
list to show how traces can also be added or removed from a plot. This can be controlled by the visible
list in updatemenus
for each button
.
If anyone is wanting to do this in a Python Dash app, here is one possible route (similar to the answer I provided for this question, but this uses go.Figure to make the graph):
import plotly
import plotly.graph_objs as go
import dash
from dash import html, dcc, callback, Output, Input
x = [1, 2, 3]
y = [1000, 10000, 100000]
y2 = [5000, 10000, 90000]
trace1 = go.Bar(x=x, y=y, name='trace1')
trace2 = go.Bar(x=x, y=y2, name='trace2', visible=False)
data = [trace1, trace2]
app = Dash(__name__)
app.layout = html.Div([
#Radio buttons for user to select their desired scale
dcc.RadioItems(
id = 'y-axis-scale-selection',
options = ['linear', 'log'],
value = 'Linear' #Set to have default linear axis
)
#Output graph
dcc.Graph(id = 'my_graph')
])
#Create graph that will have the desired axis scale
@app.callback(
Output('my_graph', 'figure'),
Input('y-axis-scale-selection', 'value'),
)
def get_graph(selected_scale):
if selected_scale == "log": #If the user selects the log scale
fig = go.Figure(data=data)
fig.update_layout(yaxis_type = "log")
else: #Default plot will have linear scale
fig = go.Figure(data=data)
return fig
if __name__ == '__main__':
app.run(debug=True)