Dash DatePickerRange 与 csv 文件

Dash DatePickerRange with csv file

我正在根据我使用 Dash 记录的(csv 文件)室外和室内温度绘制图表。我试图让图形与 DatePickerRager 组件一起工作。基本上它应该做的是编辑图表以仅显示基于选定日期的范围内的温度。但是我不知道应该怎么做。我应该在 update_graph 函数中写什么?到目前为止,这是我的代码:

import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import datetime as dt
import pandas as pd

app = dash.Dash()

iTemperature = "Indoor Temperature"

colors = {
    "graphBackground": "#212529",
    "background": "#000000",
    "text": "#ffffff"
}

app.layout = html.Div(style={"backgroundColor": colors["background"]}, children=[
    html.H1(
        children="Home Temperature",
        style={
            "textAlign": "center",
            "color": colors["text"]
        }
    ),

    html.Div(children="Outdoor and indoor temperatures", style={
        "textAlign": "center",
        "color": colors["text"]
    }),

    html.Div(children="", style={
        "color": colors["background"]
    }),

    dcc.DatePickerRange(
        id="date-picker-range",
        start_date=dt.datetime(2018, 5, 22),
        end_date=dt.datetime.now(),
        min_date_allowed=dt.datetime(2018, 5, 22),
        max_date_allowed=dt.datetime.now(),
        end_date_placeholder_text="Select a date"
    ),

    dcc.Graph(
        id="in-temp-graph",
        figure={
            "data": [
                {"x": df.date, "y": df.temperature, "type": "line", "name": iTemperature}, 
            ],
            "layout": {
                "title": iTemperature,
                "plot_bgcolor": colors["graphBackground"],
                "paper_bgcolor": colors["graphBackground"]
            }
        }
    )

])

@app.callback(
    Output("in-temp-graph", "figure"),
    [Input("date-picker-range", "start_date"),
    Input("date-picker-range", "end_date")]
)
def update_graph(start_date, end_date):
    df = pd.read_csv("iTemps.csv")
    return start_date, end_date


if __name__ == "__main__":
    app.run_server(debug=True)

感谢您的帮助!

解决方案:

import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import datetime as dt
import pandas_datareader.data as web
import pandas as pd

app = dash.Dash()

iTemperature = "Indoor Temperature"
df = pd.read_csv("iTemps.csv")

colors = {
    "graphBackground": "#212529",
    "background": "#000000",
    "text": "#ffffff"
}

app.layout = html.Div(style={"backgroundColor": colors["background"]}, children=[
    html.H1(
        children="Home Temperature",
        style={
            "textAlign": "center",
            "color": colors["text"]
        }
    ),

    html.Div(children="Outdoor and indoor temperatures", style={
        "textAlign": "center",
        "color": colors["text"]
    }),

    html.Div(children="", style={
        "color": colors["background"]
    }),

    dcc.DatePickerRange(
        id="date-picker-range",
        start_date=dt.datetime(2018, 5, 22),
        end_date=dt.datetime(2018, 8, 13),
        min_date_allowed=dt.datetime(2018, 5, 22),
        max_date_allowed=dt.datetime(2018, 8, 13),
        end_date_placeholder_text="Select a date"
    ),

    dcc.Graph(id="in-temp-graph")

])

@app.callback(
    Output("in-temp-graph", "figure"),
    [Input("date-picker-range", "start_date"),
    Input("date-picker-range", "end_date")]
)
def update_graph(start_date, end_date):

    start_date = pd.to_datetime(start_date)
    end_date = pd.to_datetime(end_date)

    filtered_df = df[df.date.between(
        dt.datetime.strftime(start_date, "%Y-%m-%d"),
        dt.datetime.strftime(end_date, "%Y-%m-%d")
    )]

    trace1 = go.Scatter(
        x = filtered_df.date,
        y = filtered_df.temperature,
        mode = "lines",
        name = iTemperature
    )

    return {
        "data": [trace1],
        "layout": go.Layout(
            title = iTemperature,
            plot_bgcolor = colors["graphBackground"],
            paper_bgcolor = colors["graphBackground"]
        )
    }

if __name__ == "__main__":
    app.run_server(debug=True)

编写回调时首先要记住的是它输出到的位置:在这种情况下,您正在构建一个回调,其输出是 dcc.Graph 元素的 "figure" 对象;也就是说,无论您在输出的 return 中输入什么,都应该 完全定义 该组件。

考虑到这一点,您首先要将 dcc.Graph 元素简化为 app.layout 中的以下内容:

dcc.Graph(id="in-temp-graph")

并在回调中执行图形对象的全部构造工作(这具有使布局部分更易于阅读的额外好处 - 相信我,这是您开始时会很高兴的事情处理更复杂的仪表板)。

您还需要在此过程中更早地导入您的 csv 文件——甚至在您开始 app.layout 部分之前;您只想导入一次数据,而不是每次用户更改日期范围时!

至于回调的构造,按照设计你的例子建议这样的事情应该有效:

@app.callback(
    Output("in-temp-graph", "figure"),
    [Input("date-picker-range", "start_date"),
    Input("date-picker-range", "end_date")]
)
def update_graph(start_date, end_date):

    # first, filter your dataset to the relevant selection
    filtered_df = df[df.date.between(
        dt.datetime.strptime(start_date,'%Y-%m-%d'),
        dt.datetime.strptime(end_date,'%Y-%m-%d'))]

    # then build the trace you'll be using based on this dataset
    trace1 = go.Scatter(
        x = filtered_df.date, 
        y = filtered_df.temperature,
        mode = 'lines',
        name: iTemperature)

    # finally, output your figure object
    return {
        'data': [trace1],
        'layout': go.Layout(
            title = iTemperature,
            plot_bgcolor = colors["graphBackground"],
            paper_bgcolor = colors["graphBackground"])

这里有一个重要警告 - 我正在假设你的提取物的性质,以及你将对其进行的转换工作:具体来说,我正在将 date-picker-range 输出的字符串重新格式化为日期时间格式(例如 dt.datetime.strptime(start_date,'%Y-%m-%d')),假设您已将数据提取的 "date" 列转换为日期时间。

但是,如果您将所述列转换为纯 date,则需要将 .date() 指令附加到上面(例如 dt.datetime.strptime(start_date,'%Y-%m-%d').date()),因为您无法将日期时间与日期进行比较。这也将用于您的日期选择器范围的默认值,因为它们当前也被格式化为日期时间。