How do I recreate the following interactive plot in Python using Plotly?
My simple example draws a bar chart with one column x and another 1-x.
GIF from Mathematica:
Slider allows for a varying x between 0 and 1.
Mathematica code:
Manipulate[BarChart[{x, 1 - x}, PlotRange -> {0, 1}],
{{x, 0.3, "Level"}, 0, 1, Appearance -> "Open"}]
UPDATE
Here is a solution which I don't like:
import plotly.graph_objs as go
from plotly.offline import init_notebook_mode, iplot
init_notebook_mode(connected=True)
import ipywidgets as widgets
Plotting:
def update_plot(x):
data = [go.Bar(
x=['1', '2'],
y=[x, 1-x]
)]
iplot(data, show_link=False)
x = widgets.FloatSlider(min=0, max=1, value=0.3)
widgets.interactive(update_plot, x=x)
Problems with this:
Starting from Plotly 3.0 this can be achieved as follows (in JupyterLab):
import plotly.graph_objects as go
from ipywidgets import interact
fig = go.FigureWidget()
bar = fig.add_bar(x=['x', '1-x'])
fig.layout = dict(yaxis=dict(range=[0,1]), height=600)
@interact(x=(0, 1, 0.01))
def update(x=0.3):
with fig.batch_update():
bar.y=[x, 1-x]
fig
Update:
From Plotly 4.0 you need to specify fig.data[0].y
instead of bar.y
.
Code below creates an interactive plot in plotly
and Dash
. It takes two inputs: slider and text box. When the code below saved as a '.py
' and the file is run in terminal, it should run a local server in the terminal. Next, copy the * Running on http://
address from this server and paste it in browser to open the plot. Most likely it would be http://127.0.0.1:8050/
. Resources: 1, 2, 3 . (Python 3.6.6
)
Important: Please note that for the slider to work, the text box value has to be reset to '0
' (zero).
Import libraries
import numpy as np
import pandas as pd
from plotly import __version__
import plotly.offline as pyo
import plotly.graph_objs as go
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
Create Dash app
app = dash.Dash()
app.layout = html.Div(
html.Div([
html.Div([html.H5("Level"),
dcc.Slider(id='slider_input',
min=0,
max=1,
step=0.005,
value=0.1,
)],style={'width': '200'}
),
html.Div(style={'height': '10'}),
html.Div(dcc.Input( id='text_input',
placeholder='Enter a value...',
type='text',
value=0.0
),style={'width': '50'}),
dcc.Graph(id='example',
figure={'data':[{'x':[1,2],
'y':[0,1],
'type':'bar',
'marker':dict(color='#ffbf00')
}],
'layout': go.Layout(title='Plot',
#xaxis = list(range = c(2, 5)),
yaxis=dict(range=[0, 1])
)
})
], style={'width':'500', 'height':'200','display':'inline-block'})
)
# callback - 1 (from slider)
@app.callback(Output('example', 'figure'),
[Input('slider_input', 'value'),
Input('text_input', 'value')])
def update_plot(slider_input, text_input):
if (float(text_input)==0.0):
q = float(slider_input)
else:
q = float(text_input)
figure = {'data': [go.Bar(x=[1,2],
y=[q, 1-q],
marker=dict(color='#ffbf00'),
width=0.5
)],
'layout': go.Layout(title='plot',
#xaxis = list(range = c(2, 5)),
yaxis=dict(range=[0, 1])
)
}
return figure
Run server
if __name__ == '__main__':
app.run_server()
Output
Edit - 1 .............................
Plot with slider only
The code below uses plotly without dash. The plot is interactive with a slider. Note that this code does not have a text input to change the plot (as above). However, the plot below should update with slider without the need to 'release' the slider to see the update. In this plot, individual traces were created for plotting.
Import libraries
import pandas as pd
import numpy as np
from plotly import __version__
%matplotlib inline
import json
import plotly.offline as pyo
import plotly.graph_objs as go
from plotly.tools import FigureFactory as FF
import cufflinks as cf
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected=True)
init_notebook_mode(connected=True)
cf.go_offline()
Create traces
traces = []
q = np.linspace(0,1, 100)
for i in range(0,len(q)):
trace = dict(
type = 'bar',
visible = False,
x=[1, 2],
y=[q[i], 1 - q[i]],
marker=dict(color='#ffbf00'),
width=0.5
)
traces.append(trace)
traces[0]['visible'] = 'True'
Create slider
steps=[]
for i in range(len(traces)):
step = dict(
method = 'restyle',
args = ['visible', [False] * len(traces)],
label=""
)
step['args'][1][i] = True # Toggle i'th trace to "visible"
steps.append(step)
sliders = [dict(
active = 10,
currentvalue = {"prefix": "Level: "},
#pad = {"t": 50},
steps = steps
)]
Create layout
layout = go.Layout(
width=500,
height=500,
autosize=False,
yaxis=dict(range=[0, 1])
)
layout['sliders'] = sliders
Plot figure
fig = go.Figure(data=traces, layout=layout)
#pyo.iplot(fig, show_link=False) # run this line to view inline in Jupyter Notebook
pyo.plot(fig, show_link=False) # run this line to view in browser
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With