updating plotly figure [every several seconds] in jupyter

Question:

I’m new to the plotly python package and I’ve faced with such problem:
There is a pandas dataframe that is updating in a loop and I have to plot data from it with plotly.
At the beginning all df.response values are None and then it starts to fill it. Here is an example:
at the beginning
after it starts to fill
I want plotly to react this changes, but I don’t know how to do it in the most "canonical" and simple way. (It would be great if data updating loop and plotly updating would work simultaneously, but if plotly will react every several seconds it would be fine too). I found some functions but don’t exactly understand how they work:

import plotly.graph_objects as go
import cufflinks as cf
from plotly.offline import init_notebook_mode

init_notebook_mode(connected=True)
cf.go_offline()

fig = go.Figure(data=go.Heatmap(z=df.response,
                                x=df.currents,
                                y=df.frequencies))

fig.update_layout(datarevision=???) # This one

...
Asked By: Ikaryssik

||

Answers:

  • given you want to update as data arrives you need an event / interrupt handling approach
  • this example uses time as the event / interupt, a dash Interval
  • simulates more data by concatenating additional data to dataframe then updates the figure in the callback
import plotly.graph_objects as go
import numpy as np
import pandas as pd
from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State

# initialise dataframe and figure
df = pd.DataFrame({"response":[], "currents":[], "frequencies":[]})
fig = go.Figure(data=go.Heatmap(z=df.response,
                                x=df.currents,
                                y=df.frequencies))



# Build App
app = JupyterDash(__name__)
app.layout = html.Div(
    [
        dcc.Graph(id="heatmap", figure=fig),
        dcc.Interval(id="animateInterval", interval=400, n_intervals=0),
    ],
)

@app.callback(
    Output("heatmap", "figure"),
    Input("animateInterval", "n_intervals"),
    State("heatmap", "figure")
)
def doUpdate(i, fig):
    global df
    df = pd.concat([df, pd.DataFrame({"response":np.random.uniform(1,5,100), "currents":np.random.randint(1,20,100), "frequencies":np.random.randint(1,50,100)})])

    return go.Figure(fig).update_traces(go.Heatmap(z=df.response,
                                x=df.currents,
                                y=df.frequencies))


# Run app and display result inline in the notebook
app.run_server(mode="inline")
Answered By: Rob Raymond

I believe this other answer has a less complicated solution than Rob Raymond’s. I would personally go with this one. Essentially you just need to wrap the Figure in a FigureWidgetthat’s it. It responds to any data changes automatically.

Although I would be interested to know if there are benefits of using Dash over Plotly alone (in a Jupyter notebook).

Answered By: Neil Traft