Python Dash 每 60 分钟更新一次数据帧

Mar*_*_CH 0 python plotly-dash

我有一个脚本,它每小时收集数据并使用 Plotly Dash 将其可视化。

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px
import pandas as pd

df = pd.read_csv("/home/pi/backup/data/data.csv").sort_values(by="Number")
df["Datetime"] = df["Datetime"].str.replace("T", " ").str.replace("Z", "")
df["Datetime"] = pd.to_datetime(df["Datetime"], format="%Y-%m-%d %H:%M:%S")
df["Datetime"] = df["Datetime"].dt.floor("H")
grouped = df.groupby(["Datetime", "Number", "Shop"]).min().reset_index()

app = dash.Dash(__name__)

tabs_styles = {
    'height': '30px'
}
tab_style = {
    'borderBottom': '1px solid #d6d6d6',
    'padding': '6px',
    'fontWeight': 'bold'
}
tab_selected_style = {
    'borderTop': '1px solid #d6d6d6',
    'borderBottom': '1px solid #d6d6d6',
    'backgroundColor': '#119DFF',
    'color': 'white',
    'padding': '6px'
}

fig = px.line(grouped, x="Datetime", y="Price", hover_name="Price",
                     facet_col='Number', color="Shop", facet_col_wrap=5,
                    width=1900, height=850)
fig.update_yaxes(matches=None, title=None)
fig.update_xaxes(title=None)
fig.update_traces(line=dict(width=1))
fig.update_layout(transition_duration=500, hovermode="x unified")

app.layout = html.Div([
    dcc.Tabs([
         dcc.Tab(label ="Overview", children=[
            dcc.Graph(
                id='example-graph',
                figure=fig
            )
        ], style=tab_style, selected_style=tab_selected_style),
        dcc.Tab(label = "Detail", children=[
            dcc.Dropdown(id='Detail_Input', options=[
                {'label': i, 'value': i} for i in df.sort_values(by=["Number"])["Number"].unique()
                ], multi=False, value=df["Number"].min()),
        dcc.Graph(id="Detail_Graph"),
        ], style=tab_style, selected_style=tab_selected_style)
    ], style=tabs_styles)
])

@app.callback(
    Output("Detail_Graph", "figure"),
    [Input("Detail_Input", "value")])
def update_figure(input):
    fig = px.line(grouped[grouped["Number"] == input], x="Datetime", y="Price", color="Shop", hover_name="Price",
                  width=1900, height=850)
    fig.update_layout(transition_duration=500, hovermode="x unified")
    return fig

if __name__ == '__main__':
    app.run_server(debug=True,port=8050,host="0.0.0.0")
Run Code Online (Sandbox Code Playgroud)

现在我想每小时更新一次数据帧“df”。或者,我可以检查文件“/home/pi/backup/data/data.csv”是否已更新,如果是,则刷新数据。在 google 或 stackoverflow 上找到了一些想法,但无法将其调整到我的脚本中(我对 Dash 非常陌生......来自 R Shiny)。

谢谢你的帮助。

emh*_*her 5

我会建议以下方法,

  • 创建一个更新数据的回调 (A)。虽然您可以手动进行更新(即检查文件时间戳并根据需要进行更新),但使用带有超时的服务器端缓存(例如Flask-Caching)可能会更容易。

  • 创建第二个回调 (B),当回调 A 中的数据发生变化时绘制图形。

如果你想要实时更新(即不刷新页面),你应该使用一个Interval组件来触发回调 A。这是一个使用dash_extensions==0.0.28包的小例子,

import dash_html_components as html
import dash_core_components as dcc

from datetime import datetime
from dash_extensions.enrich import Dash, Trigger, Output, Input, ServersideOutput, FileSystemStore

# Create server side store to hold the data.
fss = FileSystemStore(cache_dir="some_dir", default_timeout=10)  # timeout in seconds, i.e. yours should be 3600
# Create an example app.
app = Dash(__name__)
app.layout = html.Div([
    html.Div(id="log"),  # logging of data, a mock replacement of your graph
    dcc.Store(id="store"),  # store that holds the data reference
    dcc.Interval(id="trigger", interval=1000),  # trigger to invoke data refresh attempt, defaults to once per second
])


@app.callback(ServersideOutput("store", "data", session_check=False, backend=fss),
              Trigger("trigger", "n_intervals"), memoize=True)
def update_data():
    return datetime.now()  # put your update logic here


@app.callback(Output("log", "children"), Input("store", "data"))
def show_data(data):
    return f"Data were collected at {data}, current time is {datetime.now()}"  # put your graph drawing code here


if __name__ == "__main__":
    app.run_server()
Run Code Online (Sandbox Code Playgroud)

免责声明:我是dash_extensions.