【问题标题】:Dash Python: Add date-picker and sidebar to dashboardDash Python:将日期选择器和侧边栏添加到仪表板
【发布时间】:2021-07-07 15:17:18
【问题描述】:

我在使用 Dash 构建的仪表板中有一个侧边栏和一个日期选择器。但是,我无法根据所选日期范围正确加载图表。数据源可以在下面的链接中找到,但是,我将“Year”列的值更改为“YYYY-MM-DD”格式的日期。

Data Source

非常感谢您的帮助。

输出错误:

FileNotFoundError: [Errno 2] No such file or directory: 'iranian_students.csv'
ID not found in layout

Attempting to connect a callback Input item to component:
  "date-range"
but no components with that id exist in the layout.

If you are assigning callbacks to components that are
generated by other callbacks (and therefore not in the
initial layout), you can suppress this exception by setting
`suppress_callback_exceptions=True`.
This ID was used in the callback(s) for Output(s):
  students.figure
  students.figure
ID not found in layout

Attempting to connect a callback Output item to component:
  "students"
but no components with that id exist in the layout.

If you are assigning callbacks to components that are
generated by other callbacks (and therefore not in the
initial layout), you can suppress this exception by setting
`suppress_callback_exceptions=True`.
This ID was used in the callback(s) for Output(s):
  students.figure

我的代码:

# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
from flask import Flask
import pandas as pd
from pandas import DataFrame
from pandas import json_normalize
import pymongo
from pymongo import MongoClient
import plotly.graph_objs as go
import plotly.offline as pyo
import plotly.express as px
import numpy as np
import pytz, time
from datetime import datetime, tzinfo, timezone, timedelta, date
import dash_bootstrap_components as dbc
import random
from sqlalchemy import create_engine
from plotly.subplots import make_subplots


# %%
# constants
df = pd.read_csv('Bootstrap\Side-Bar\iranian_students.csv')
localTimezone = pytz.timezone('Africa/Cairo')
datetimeNow = datetime.now(localTimezone)


# %%
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.FLATLY],
                meta_tags=[{'name': 'viewport',
                            'content': 'width=device-width, initial-scale=1.0'}]
                )


# %%
def serve_layoutOnReload():
    # styling the sidebar
    SIDEBAR_STYLE = {
        "position": "fixed",
        "top": 0,
        "left": 0,
        "bottom": 0,
        "width": "16rem",
        "padding": "2rem 1rem",
        "background-color": "#f8f9fa",
    }

    # padding for the page content
    CONTENT_STYLE = {
        "margin-left": "18rem",
        "margin-right": "2rem",
        "padding": "2rem 1rem",
    }

    sidebar = html.Div(
        [
            html.H2("Sidebar", className="display-4"),
            html.Hr(),
            html.P(
                "Number of students per education level", className="lead"
            ),
            dbc.Nav(
                [
                    dbc.NavLink("Home", href="/", active="exact"),
                    dbc.NavLink("Page 1", href="/page-1", active="exact"),
                    dbc.NavLink("Page 2", href="/page-2", active="exact"),
                ],
                vertical=True,
                pills=True,
            ),
        ],
        style=SIDEBAR_STYLE,
    )

    content = html.Div(id="page-content", children=[], style=CONTENT_STYLE)

    web_layout = html.Div([
        dcc.Location(id="url"),
        sidebar,
        content
    ])

    return web_layout


app.layout = serve_layoutOnReload
# app.layout = html.Div([
#     dcc.Location(id="url"),
#     sidebar,
#     content
# ])


# %%
@app.callback(
    Output("page-content", "children"),
    [Input("url", "pathname")]
)
def render_page_content(pathname):
    if pathname == "/":
        return [
                html.H1('Kindergarten',
                        style={'textAlign':'center'}),
                dbc.Container([
                        dbc.Row([
                            dbc.Col([
                                html.P("Date picker:", className='text-right font-weight-bold mb-4'),
                                ],xs=12, sm=12, md=12, lg=5, xl=5),
                            dbc.Col([
                                dcc.DatePickerRange(id='date-range', 
                                                    min_date_allowed=date(2020, 6, 1),
                                                    max_date_allowed=datetimeNow.date(),
                                                    start_date=datetimeNow.date() - timedelta(days=7),
                                                    end_date=datetimeNow.date(), ),
                                ],xs=12, sm=12, md=12, lg=5, xl=5),], no_gutters=True, justify='center'),
                        
                        dbc.Row(
                            dbc.Col(html.H2(" ", className='text-center text-primary mb-4'), width=12)
                            ),
                        
                        dbc.Row([
                            dbc.Col([
                                dcc.Graph(id="students", figure={}),
                            ], xs=12, sm=12, md=12, lg=5, xl=5),], justify='center')
                ], fluid=True)
            ]
    elif pathname == "/page-1":
        return [
                html.H1('Grad School',
                        style={'textAlign':'center'}),
                dcc.Graph(id='bargraph',
                         figure=px.bar(df, barmode='group', x='Date',
                         y=['Girls Grade School', 'Boys Grade School']))
                ]
    elif pathname == "/page-2":
        return [
                html.H1('High School',
                        style={'textAlign':'center'}),
                dcc.Graph(id='bargraph',
                         figure=px.bar(df, barmode='group', x='Date',
                         y=['Girls High School', 'Boys High School']))
                ]
    # If the user tries to reach a different page, return a 404 message
    return dbc.Jumbotron(
        [
            html.H1("404: Not found", className="text-danger"),
            html.Hr(),
            html.P(f"The pathname {pathname} was not recognised..."),
        ]
    )


# %%
@app.callback([Output("students", "figure")],
                [Input("date-range", "start_date"),
                 Input("date-range", "end_date")])
def update_charts(start_date, end_date):
    # read data upon refresh browser
    df = pd.read_csv('iranian_students.csv')

    # masks
    mask1 = (
        (df.Date >= pd.to_datetime(start_date))
        & (df.Date <= pd.to_datetime(end_date))
    )# daily sgym signups

    # filtered dataframes
    filtered_data1 = df.loc[mask1, :].reset_index(drop=True)

    # plots
    # daily sgym signups
    trace = []
    trace.append(go.Bar(
            x = filtered_data1['Date'],
            y = filtered_data1['Girls Kindergarten'],
            name = 'Count of students'
        ))
    
    # add moving average
    filtered_data1['Moving Avg'] = filtered_data1['Girls Kindergarten'].rolling(window=7, min_periods=1).mean()
    trace.append(go.Scatter(x=filtered_data1['Date'], y=filtered_data1['Moving Avg'], name = 'Rolling Mean=7'))
    
    students_fig = {'data': trace,
                            'layout': go.Layout(
                                {"title": {"text": "Student Count\n"
                                            '('+str(start_date)+' to '+str(end_date)+')', 
                                                "x": 0.05, "xanchor": "left"},
                                    "xaxis": {"fixedrange": False, 'title':'Date',   
                                                'tickmode':'linear', 'automargin':True},
                                    "yaxis": {"fixedrange": False, 'title':'Count of Signups'},
                                    'xaxis_tickformat':'%d %b',
                                    'title_font_size': 14,
                                    'hovermode':'closest',
                                    'legend_title_text':'Gym',
                                    'hovermode':'closest',
                                    },)   }
    
    return students_fig


# %%
if __name__=='__main__':
    app.run_server(debug=True, port=3000)

【问题讨论】:

    标签: python plotly-dash


    【解决方案1】:

    第一个错误是告诉你问题从哪里开始。问题出在您在更新图表时定义的文件路径中。

    而不是这个:

     def update_charts(start_date, end_date):
            # read data upon refresh browser
            df = pd.read_csv('iranian_students.csv')
    

    你需要这样做:

     def update_charts(start_date, end_date):
            # read data upon refresh browser
            df = pd.read_csv('Bootstrap\Side-Bar\iranian_students.csv')
    

    第二个问题是你 不带括号调用函数serve_layoutOnReload?

    app.layout = serve_layoutOnReload
    

    而不是

    app.layout = serve_layoutOnReload()
    

    第三个问题是如何定义布局。请参阅this 讨论以供参考。This 1 月份的讨论使用与您相同的代码/数据库,并且他们面临相同的问题。

    我会尝试像这样直接定义布局:

    app.layout = html.Div([])
    

    【讨论】:

    • 是的,您有不止一个错误。您应该为每个错误提出单独的问题以获得完整的答案。我更新了答案。
    • 感谢您的帮助,但您真的运行了完整的代码吗?我在这里按照 Dash 指南将 app.layout 定义为实际的函数实例,没有括号:dash.plotly.com/live-updates
    猜你喜欢
    • 2015-09-24
    • 1970-01-01
    • 2019-12-26
    • 1970-01-01
    • 1970-01-01
    • 2016-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多