Je souhaite surveiller certaines données en direct et permettre à l'utilisateur de sélectionner ses propres plages lorsqu'il interagit avec les graphiques. J'ai créé ce petit exemple (obtenu à partir du tutoriel) et le problème est que chaque fois que je mets à jour le tracé, tout est réinitialisé puisque update_graph_live()
renvoie une nouvelle figure Plotly. (voir l'exemple ci-dessous)
Est-il possible de mettre à jour uniquement les données, afin que la figure ne soit pas rechargée et réinitialisée à la vue/paramètres par défaut? J'utilisais d3.js auparavant et envoyais les données via des websockets, donc je pouvais filtrer les données dans le navigateur. Mais je voudrais le faire directement avec Dash.
import dash
from dash.dependencies import Output, Event
import dash_core_components as dcc
import dash_html_components as html
from random import random
import plotly
app = dash.Dash(__name__)
app.layout = html.Div(
html.Div([
html.H4('Example'),
dcc.Graph(id='live-update-graph'),
dcc.Interval(
id='interval-component',
interval=1*1000
)
])
)
@app.callback(Output('live-update-graph', 'figure'),
events=[Event('interval-component', 'interval')])
def update_graph_live():
fig = plotly.tools.make_subplots(rows=2, cols=1, vertical_spacing=0.2)
fig['layout']['margin'] = {
'l': 30, 'r': 10, 'b': 30, 't': 10
}
fig['layout']['legend'] = {'x': 0, 'y': 1, 'xanchor': 'left'}
fig.append_trace({
'x': [1, 2, 3, 4, 5],
'y': [random() for i in range(5)],
'name': 'Foo',
'mode': 'lines+markers',
'type': 'scatter'
}, 1, 1)
fig.append_trace({
'x': [1, 2, 3, 4, 5],
'y': [random() for i in range(5)],
'name': 'Bar',
'type': 'bar'
}, 2, 1)
return fig
if __name__ == '__main__':
app.run_server(debug=True)
Si vous ajoutez animate=True
à ton dcc.Graph
les traces basculées et le zoom/marqueur/tout ce qui est conservé, mais cela ne fonctionne pas pour les graphiques à barres (bien que cela devrait fonctionner: https://github.com/plotly/plotly.js/pull/114 ). De plus, au lieu de renvoyer le figure
complet, il vous suffit de renvoyer les traces.
La meilleure solution possible que je pourrais trouver est de le diviser en deux graphiques, mais vous obtiendriez au moins la plupart des fonctionnalités souhaitées.
import dash
from dash.dependencies import Output, Event
import dash_core_components as dcc
import dash_html_components as html
from random import random
import plotly
app = dash.Dash(__name__)
app.layout = html.Div(
html.Div([
dcc.Graph(id='live-update-graph-scatter', animate=True),
dcc.Graph(id='live-update-graph-bar'),
dcc.Interval(
id='interval-component',
interval=1*1000
)
])
)
@app.callback(Output('live-update-graph-scatter', 'figure'),
events=[Event('interval-component', 'interval')])
def update_graph_scatter():
traces = list()
for t in range(2):
traces.append(plotly.graph_objs.Scatter(
x=[1, 2, 3, 4, 5],
y=[(t + 1) * random() for i in range(5)],
name='Scatter {}'.format(t),
mode= 'lines+markers'
))
return {'data': traces}
@app.callback(Output('live-update-graph-bar', 'figure'),
events=[Event('interval-component', 'interval')])
def update_graph_bar():
traces = list()
for t in range(2):
traces.append(plotly.graph_objs.Bar(
x=[1, 2, 3, 4, 5],
y=[(t + 1) * random() for i in range(5)],
name='Bar {}'.format(t)
))
layout = plotly.graph_objs.Layout(
barmode='group'
)
return {'data': traces, 'layout': layout}
if __name__ == '__main__':
app.run_server(debug=True)
Pour le graphique en barres, encadrés et histogrammes, vous ne devez pas utiliseranimate=True
sinon le tracé sera hors de la zone de traçage. De plus, Event est déconseillé par Dash Plotly, utilisez plutôt Input.
import dash
from dash.dependencies import Output,Input
import dash_core_components as dcc
import dash_html_components as html
from random import random
import plotly
app = dash.Dash(__name__)
app.layout = html.Div(
html.Div([
dcc.Graph(id='live-update-graph-scatter', animate=True),
dcc.Graph(id='live-update-graph-bar'),
dcc.Interval(
id='interval-component',
interval=1*1000
)
])
)
@app.callback(Output('live-update-graph-scatter', 'figure'),
[Input('interval-component', 'interval')])
def update_graph_scatter():
traces = list()
for t in range(2):
traces.append(plotly.graph_objs.Scatter(
x=[1, 2, 3, 4, 5],
y=[(t + 1) * random() for i in range(5)],
name='Scatter {}'.format(t),
mode= 'lines+markers'
))
return {'data': traces}
@app.callback(Output('live-update-graph-bar', 'figure'),
[Input('interval-component', 'interval')])
def update_graph_bar():
traces = list()
for t in range(2):
traces.append(plotly.graph_objs.Bar(
x=[1, 2, 3, 4, 5],
y=[(t + 1) * random() for i in range(5)],
name='Bar {}'.format(t)
))
layout = plotly.graph_objs.Layout(
barmode='group'
)
return {'data': traces, 'layout': layout}
if __name__ == '__main__':
app.run_server(debug=True)