带有CSV文件的破折号DatePickerRange

时间:2018-08-20 09:58:31

标签: python python-3.x pandas plotly-dash

我正在使用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)

1 个答案:

答案 0 :(得分:0)

编写回调时要记住的第一件事就是它的输出目的地:在这种情况下,您要构建一个回调,其输出是dcc.Graph元素的“ figure”对象;也就是说,无论您在输出返回中输入什么内容,都应该完全定义该组件。

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

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

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

您还希望在此过程中更早地导入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"])

这里的主要警告-我对提取物的性质以及将要进行的转换工作进行假设:具体地说,我正在将日期选择器范围输出的字符串重新格式化为日期时间格式(例如dt.datetime.strptime(start_date,'%Y-%m-%d')),前提是您已将摘录的“日期”列转换为日期时间。

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