2017-09-06 3 views
3

Je veux surveiller certaines données en direct et permettre à l'utilisateur de sélectionner leurs propres gammes lors de l'interaction avec les parcelles. J'ai créé ce petit exemple (obtenu à partir du tutoriel) et le problème est, chaque fois que je mets à jour l'intrigue, tout se réinitialise puisque update_graph_live() renvoie un nouveau chiffre Plotly. (voir l'exemple ci-dessous)Mise à jour en direct uniquement les données dans Dash/plotly

Est-il possible de mettre à jour uniquement les données, de sorte que la figure ne soit pas rechargée et réinitialisée à la vue/aux paramètres par défaut? J'utilisais d3.js avant et envoyais les données via des Websockets, donc je pouvais filtrer les données dans le navigateur. Mais j'aimerais 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) 

Répondre

4

Si vous ajoutez à vos animate=Truedcc.Graph les traces basculés et sélectionné zoom/marqueur/tout ce qui est conservé, mais cela ne fonctionne pas pour les parcelles de bar (bien qu'il devrait fonctionner: https://github.com/plotly/plotly.js/pull/1143). En outre, au lieu de renvoyer le figure complet, vous devez simplement 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 désirées.

enter image description here

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)