Altair中日期字段调用LOESS平滑时间序列绘图异常求助
Altair 时间序列LOESS平滑异常解决方案
问题根因
- 直接对日期类型字段调用
transform_loess返回空白图表:Altair依赖的Vega-Lite底层LOESS实现要求输入自变量为数值类型,传入时间类型时无法完成数值计算,直接返回空结果。 - 手动转时间戳后X轴显示异常:Python标准库
datetime.timestamp()返回的是秒级Unix时间戳,而Vega/JavaScript生态默认使用毫秒级时间戳,单位差1000倍导致日期解析完全错位,仅调整轴格式参数无法修复。
最优实现方案
不需要提前用pandas做分组平滑预处理,直接在Altair的转换链内完成时间格式适配,原生支持分组平滑,代码可直接复用:
import altair as alt from vega_datasets import data # 加载示例数据 temps = data.seattle_temps() temps = temps[temps.date < '2010-01-15'] alt.Chart(temps).mark_line(color='steelblue', size=2).encode( # 直接指定平滑后输出的时间字段为时间类型,自定义轴显示格式 x=alt.X('smooth_date:T', axis=alt.Axis(format='%Y-%b-%d %H:%M')), y=alt.Y('smooth_temp:Q', title='Temperature') ).transform_calculate( # 内置转换层将原日期转为毫秒级时间戳,无需修改原始DataFrame date_ts='toDate(datum.date).getTime()' ).transform_loess( on='date_ts', loess='temp', bandwidth=0.3, as_=['smooth_date', 'smooth_temp'], # 多变量分组场景直接传入分组字段即可,无需手动写pandas groupby循环 # 例:groupby=['site', 'sensor_id'] )
扩展:原始数据+平滑线叠加绘制
如果需要同时展示原始观测值和平滑趋势,可以用图层叠加实现:
# 原始数据层(半透明散点) raw_layer = alt.Chart(temps).mark_point(opacity=0.3, color='gray').encode( x='date:T', y='temp:Q' ) # LOESS平滑线层 smooth_layer = alt.Chart(temps).mark_line(color='crimson', size=2).encode( x=alt.X('smooth_date:T', axis=alt.Axis(format='%Y-%b-%d')), y='smooth_temp:Q' ).transform_calculate( date_ts='toDate(datum.date).getTime()' ).transform_loess( on='date_ts', loess='temp', bandwidth=0.3, as_=['smooth_date', 'smooth_temp'] ) # 组合输出图表 raw_layer + smooth_layer
分组平滑使用说明
针对多变量分组场景,只需要两步即可完成:
- 在
transform_loess的groupby参数中传入需要分组的字段名列表 - 在编码层添加对应分组字段的映射(如
color='分组字段:N'做颜色区分,或做分面)
不需要提前对数据集做分组、循环平滑的繁琐操作。
内容的提问来源于stack exchange,提问作者sisyphos
相关产品推荐
相关产品推荐

