связать обновление графика plotly с обновлением dataframe

У меня есть датафрейм, который обновляется в цикле. Изначально он выглядит следующим образом
введите сюда описание изображения
А затем я активирую скрипт в ячейке юпитера и значения NaN начинают заполняться конкретными числами. По этому фрейму должен строиться heatmap, я решил попробовать для этого plotly:
Фрейм в начальный момент времени
Фрейм начал заполняться
Меня интересует, как сделать так, чтобы plotly автоматически реагировал на изменения в датафрейме и обновлял график, чтобы не пришлось каждый раз останавливать расчет и проверять, как выглядит график в текущий момент.
Как я понимаю, в этой библиотеке должно быть какое то элегантное решение, без нагромождения дополнительных циклов.
Я нашел один метод в документации, но не уверен, что он подойдет для этих целей, так как там очень смутно описан принцип действия:

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=???) # вот этот

Хотелось бы узнать, как можно это реализовать наиболее простым способом?


Ответы (1 шт):

Автор решения: Ikaryssik

Итак, к какому решению пришел я сам:
Здесь логичнее не обновлять plotly график вручную, а доверить это библиотеке Dash. Можно построить простенькое dash приложение непосредственно в ноутбуке, чтобы не приходилось открывать локальный сервер в браузере.

  • Если вы хотите обновлять данные по мере их поступления, вам нужен подход, основанный на обработке событий (event). В данном примере этим самым событием является время dash Interval
# 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")

Более подробно про то, как строятся Dash приложения и как использовать те или иные функции можно прочитать на странице с туториалами от Dash
Вот также неплохое вводное видео по теме
https://www.youtube.com/watch?v=hSPmj7mK6ng

→ Ссылка