Interactive plot with Slider using Plotly

十年热恋 提交于 2019-12-11 18:38:41

问题


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:

  • The plot twinkles when the slider is moved
  • The slider is misplaced
  • The increment is not granular enough
  • I cannot specify a precise value myself

回答1:


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 




回答2:


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.



来源:https://stackoverflow.com/questions/51367567/interactive-plot-with-slider-using-plotly

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!