Plotly Express OLS趋势线异常问题求助
问题
手里有一组带周季节性的交通事故数量数据集,用Plotly Express的OLS趋势线代码:
fig = px.scatter(df, x='Open date', y='Total Cases', trendline="ols", trendline_scope="overall") fig.show()
得到的趋势线是锯齿状的,而且趋势线摘要里的x1系数接近1,结果完全不合理。但换成lowess方法或者用Plotly官方示例就没问题。另外用matplotlib结合numpy的代码:
import matplotlib.pyplot as plt import matplotlib.dates as mdates import numpy as np x = mdates.date2num(daily['Open date']) y= daily['Total Cases'] z = np.polyfit(x, daily['Total Cases'], 1) p = np.poly1d(z) # 绘图 daily.plot('Open date', 'Total Cases') plt.plot(x, p(x), "r--")
却能生成正常的趋势线。想问是不是遗漏了平滑参数,或者违反了OLS的假设?
复现用的前30天数据(用索引代替日期):
{1: 580, 2: 585, 3: 1474, 4: 1100, 5: 966, 6: 986, 7: 1068, 8: 655, 9: 563, 10: 1130, 11: 956, 12: 863, 13: 840, 14: 809, 15: 657, 16: 470, 17: 1039, 18: 778, 19: 764, 20: 841, 21: 829, 22: 604, 23: 475, 24: 1041, 25: 785, 26: 690, 27: 711, 28: 823, 29: 616, 30: 462}
原因分析与解决办法
核心原因:Plotly对日期型变量的OLS处理逻辑
Plotly Express在处理日期类型的x轴时,不会像numpy那样把日期转成连续的数值(比如mdates.date2num生成的浮点数),而是会把日期当作离散的分类变量或按时间单位生成编码值,导致OLS模型拟合的不是“时间-事故数”的线性趋势,而是把每个日期当作独立变量去适配,最终出现锯齿状的伪趋势线,系数结果自然完全不合理。
解决办法
直接把日期转成连续的数值型变量,再传给Plotly的OLS趋势线:
- 给数据集新增一列,将日期转成连续数值(比如从起始日开始的天数,或用
mdates.date2num转换):
import matplotlib.dates as mdates df['date_num'] = mdates.date2num(df['Open date'])
- 用这个数值型列作为x轴绘制OLS趋势线,可选将x轴标签改回日期格式:
fig = px.scatter(df, x='date_num', y='Total Cases', trendline="ols", trendline_scope="overall") fig.update_xaxes(tickvals=df['date_num'], ticktext=df['Open date'].dt.strftime('%Y-%m-%d')) fig.show()
关于OLS假设的补充
你的数据存在周季节性,本质上存在序列自相关,这确实违反了OLS“误差项独立同分布”的假设,但这不是当前锯齿状趋势线的直接原因——numpy的polyfit同样没处理自相关,但因为把日期当作连续数值拟合,所以能得到正常的线性趋势。如果要修正季节性带来的OLS偏差,可以考虑在模型中加入周几的虚拟变量,或者先用STL等方法做季节性分解,去掉季节项后再拟合趋势。
内容的提问来源于stack exchange,提问作者jcf
相关产品推荐
相关产品推荐

