Altair中基于日期转换列的选择器无法显示图表对象求助
使用Altair基于一战轰炸事件CSV制作可视化,目标实现两个筛选图表:点击时间图表(bombing_over_time)中的事件后,分别展示同年、同月的所有轰炸事件。已从MSNDATE列提取month和year(int64类型),数据集头部如下:
# the head of the dataset month year 10 1917 10 1917 10 1917 10 1917 10 1917
转换及图表代码如下:
df_filtered.loc[:, 'month'] = pd.to_datetime(df_filtered['MSNDATE'], format='%M').dt.month.astype(int) df_filtered.loc[:, 'year'] = pd.to_datetime(df_filtered['MSNDATE'], format='%Y').dt.year.astype(int) year_selection = alt.selection_point(fields=['year'], nearest=True, on='click') month_selection = alt.selection_point(fields=['month'], nearest=True, on='click') # 同年事件图表 same_year_incidents = alt.Chart(df_filtered, title='Incidents in the same year').mark_circle(opacity=op_var).encode( alt.X('WEAPONWEIGHT', axis=alt.Axis(title='Weapon weight')), alt.Y('BOMBLOAD', axis=alt.Axis(title='Bombload'), scale=alt.Scale(nice=10, zero=False, padding=1)), color = attackercolor, size = alt.value(150), tooltip = ["COUNTRY", "TGTCOUNTRY", 'MSNDATE:T', 'WEAPONWEIGHT', 'BOMBLOAD'] ).transform_filter( year_selection ).add_params( op_var, brush ).interactive().properties(height=200, width=650) # 同月事件图表 same_month_incidents = alt.Chart(df_filtered, title='Incidents in the same month').mark_circle(opacity=op_var).encode( alt.X('WEAPONWEIGHT', axis=alt.Axis(title='Weapon weight')), alt.Y('BOMBLOAD', axis=alt.Axis(title='Bombload'), scale=alt.Scale(nice=10, zero=False, padding=1)), color = attackercolor, size = alt.value(150), tooltip = ["COUNTRY", "TGTCOUNTRY", 'MSNDATE:T', 'WEAPONWEIGHT', 'BOMBLOAD'] ).transform_filter( month_selection ).add_params( op_var, brush ).properties(height=200, width=650)
初始运行图表显示正常,但点击bombing_over_time图表中的事件(如MSNDATE为14/9/1918的条目)后,两个筛选图表无任何内容显示。
日期转换格式错误
代码中用format='%M'解析MSNDATE完全错误:%M代表分钟而非月份;format='%Y'仅解析年份部分,无法处理14/9/1918这类完整日期字符串,导致month和year列提取的值与实际日期不符,后续筛选自然匹配不到数据。选择器未关联时间图表
当前定义的year_selection和month_selection是独立选择器,未绑定到bombing_over_time图表的点击事件。点击时间图表时,这两个选择器无法获取对应年份/月份值,导致筛选条件为空,图表无数据显示。
1. 修正日期转换代码
假设MSNDATE格式为日/月/年(如14/9/1918),用正确格式解析日期后提取月份和年份:
# 解析完整日期,格式需匹配你的实际日期格式 df_filtered['MSNDATE'] = pd.to_datetime(df_filtered['MSNDATE'], format='%d/%m/%Y') # 提取月份和年份 df_filtered['month'] = df_filtered['MSNDATE'].dt.month.astype(int) df_filtered['year'] = df_filtered['MSNDATE'].dt.year.astype(int)
若日期格式为月/日/年,需将format改为%m/%d/%Y。
2. 统一选择器并关联时间图表
在bombing_over_time图表中定义一个选择器,同时获取点击事件的year和month值,再在两个筛选图表中分别过滤:
# 定义选择器,绑定到时间图表的点击事件 date_selection = alt.selection_point(fields=['year', 'month'], nearest=True, on='click') # 同年事件图表:仅匹配年份 same_year_incidents = alt.Chart(df_filtered, title='Incidents in the same year').mark_circle(opacity=op_var).encode( alt.X('WEAPONWEIGHT', axis=alt.Axis(title='Weapon weight')), alt.Y('BOMBLOAD', axis=alt.Axis(title='Bombload'), scale=alt.Scale(nice=10, zero=False, padding=1)), color=attackercolor, size=alt.value(150), tooltip=["COUNTRY", "TGTCOUNTRY", 'MSNDATE:T', 'WEAPONWEIGHT', 'BOMBLOAD'] ).transform_filter( alt.datum.year == date_selection.year ).add_params( op_var, brush ).interactive().properties(height=200, width=650) # 同月事件图表:同时匹配年份和月份(避免不同年份同月混淆) same_month_incidents = alt.Chart(df_filtered, title='Incidents in the same month').mark_circle(opacity=op_var).encode( alt.X('WEAPONWEIGHT', axis=alt.Axis(title='Weapon weight')), alt.Y('BOMBLOAD', axis=alt.Axis(title='Bombload'), scale=alt.Scale(nice=10, zero=False, padding=1)), color=attackercolor, size=alt.value(150), tooltip=["COUNTRY", "TGTCOUNTRY", 'MSNDATE:T', 'WEAPONWEIGHT', 'BOMBLOAD'] ).transform_filter( (alt.datum.year == date_selection.year) & (alt.datum.month == date_selection.month) ).add_params( op_var, brush ).properties(height=200, width=650) # 在时间图表中绑定选择器 bombing_over_time = alt.Chart(df_filtered, title='Bombing Over Time').mark_point().encode( x='MSNDATE:T', # 其他编码字段 ).add_params(date_selection)
3. 验证数据正确性
运行代码前先检查month和year列是否正确:
print(df_filtered[['MSNDATE', 'month', 'year']].head())
确保提取的月份和年份与原始MSNDATE一致。
内容的提问来源于stack exchange,提问作者Terry563

