Dash日期范围选择器无图表显示问题求助及代码排查
问题描述
在Jupyter Notebook中使用Dash开发日期范围选择器功能,但图表无法正常显示,使用NYC交通事故数据集,原代码如下:
collisions = ( pd.read_csv("NYC_Collisions.csv") .astype({"ACCIDENT_DATE": "datetime64[ns]"}) .loc[:,["ACCIDENT_DATE", "BOROUGH", "COLLISION_ID"]] .groupby(["ACCIDENT_DATE", "BOROUGH"], as_index=False) .count() .rename(columns={ "COLLISION_ID":"COLLISIONS", "ACCIDENT_DATE":"DATE"}) ) collisions.head() from datetime import datetime from datetime import date app = Dash(__name__) app.layout = html.Div([ dcc.DatePickerRange( id="date picker", min_date_allowed=collisions["DATE"].min(), max_date_allowed=collisions["DATE"].max(), initial_visible_month=collisions["DATE"].max(), start_date=collisions["DATE"].min(), end_date=date(2022,1,1), ), dcc.Graph(id="graph") ]) @app.callback(Output("graph", "figure"), [Input("date picker", "start_date"), Input("date picker", "end_date"),]) def plot_collisions_bar(start_date, end_date): fig = px.bar( (collisions .loc[collisions["DATE"].between(start_date, end_date)] .groupby("BOROUGH", as_index=False) .sum() ) , x="COLLISIONS", y="BOROUGH", title=f"Traffic Accidents in NYC between {start_date[:10]} and {end_date[:10]}" ) return fig if __name__ == "__main__": app.run_server(mode="inline", port=8001, width="60%")
错误排查与修复要点
- 日期类型不匹配:
dcc.DatePickerRange返回的start_date/end_date是字符串格式,而数据集的DATE列是datetime64[ns]类型,直接用between比较会筛选不到数据,导致图表为空。需将字符串日期转为datetime格式后再做筛选。 - 组件ID含空格:
id="date picker"包含空格,虽Dash允许,但可能引发回调匹配的潜在问题,建议改为"date-picker"这类无空格命名。 - 初始日期类型不一致:
start_date用了Pandas datetime对象,end_date用了Python原生date对象,统一类型可避免兼容性问题。 - 无数据处理:添加空数据判断,避免因筛选后无数据导致图表报错。
修正后的完整代码
import pandas as pd import plotly.express as px from dash import Dash, html, dcc, Input, Output from datetime import date # 数据预处理 collisions = ( pd.read_csv("NYC_Collisions.csv") .astype({"ACCIDENT_DATE": "datetime64[ns]"}) .loc[:,["ACCIDENT_DATE", "BOROUGH", "COLLISION_ID"]] .groupby(["ACCIDENT_DATE", "BOROUGH"], as_index=False) .count() .rename(columns={ "COLLISION_ID":"COLLISIONS", "ACCIDENT_DATE":"DATE"}) ) # 初始化Dash应用 app = Dash(__name__) app.layout = html.Div([ dcc.DatePickerRange( id="date-picker", min_date_allowed=collisions["DATE"].min(), max_date_allowed=collisions["DATE"].max(), initial_visible_month=collisions["DATE"].max(), start_date=collisions["DATE"].min().date(), end_date=date(2022,1,1), ), dcc.Graph(id="graph") ]) @app.callback( Output("graph", "figure"), [Input("date-picker", "start_date"), Input("date-picker", "end_date")] ) def plot_collisions_bar(start_date, end_date): # 转换日期格式,匹配数据集类型 start_dt = pd.to_datetime(start_date) end_dt = pd.to_datetime(end_date) filtered_data = collisions.loc[collisions["DATE"].between(start_dt, end_dt)] # 处理空数据场景 if filtered_data.empty: return px.bar(title="该日期范围内无事故数据") aggregated_data = filtered_data.groupby("BOROUGH", as_index=False).sum() fig = px.bar( aggregated_data, x="COLLISIONS", y="BOROUGH", orientation="h", title=f"Traffic Accidents in NYC between {start_date[:10]} and {end_date[:10]}" ) return fig if __name__ == "__main__": app.run_server(mode="inline", port=8001, width="60%")
内容的提问来源于stack exchange,提问作者user19791361
相关产品推荐
相关产品推荐

