python——分组滚动OLS回归和预测
我有一个熊猫数据框,里面有一些关于赛车手的数据。相关列如下所示:
|Date |Name |Distance |avg_speed_calc
|---- |---- |---- |----
|9/6/20 | Smith | 8 | 85.6
|9/6/20 | Douglas | 8 | 84.9
|9/6/20 | Mostern | 8 | 84.3
.......
|Date |Name |Distance |avg_speed_calc
|:---- |:---- |:----- |:----
|4/5/21 | Smith | 6 | 88.7
|4/5/21 | Robinson | 6 | 89.3
|4/5/21 | Thomas | 6 | 87.5
在上面的数据中,每场比赛都有不同数量的参赛者,并不是每个参赛者都参加每项赛事——有些甚至可能只有一个行条目。
我正在尝试制作一个简单的 OLS,通过仅将距离与他的 average_speed_calc 进行回归来了解每个赛车手的首选距离。因为我希望在每次比赛后更新计算,所以我一直在尝试使用 StatsModels 中的 RollingOLS。在几年前一个有点类似的问题的帮助下,我的代码目前看起来像这样:
from statsmodels.regression.rolling import RollingOLS
import pandas as pd
import numpy as np
dist_pref = df.groupby(["Name"]).apply(lambda x: RollingOLS(endog=x['avg_speed_calc'], exog=sm.add_constant(x['Distance']),min_nobs=2)).fit().params)
但是,这会引发消息“ValueError:无法将输入数组从形状 (0) 广播到形状 (1)”,到目前为止我还无法修复。
我还尝试了基于另一个旧问题的辅助功能,但无济于事:
def ols_res(x, y):
return pd.Series(RollingOLS(y, x).fit().predict)
df_dist = df.groupby(['Name']).apply(lambda x : x['Distance'].apply(ols_res, y=x['avg_speed_calc']))
理想情况下,我想预测当天比赛的 average_speed_calc,仅使用之前比赛的数据,以便我可以将其与该行中报告的实际 avg_speed_calc 进行比较。我想为每个系数/截距创建单独的 DataFrame 列,然后将它们向下移动一个,然后使用这些数字以及当前比赛的距离来进行预测,但也许有一种更有效的方法。
假设生成的数据框然后按日期和赛车手排序,我想要的最终输出(需要两次或更多之前的比赛进行预测)是一个数据框,其中包含每个赛车手的信息,如下所示:
日期 | 名称 | 距离 | 平均速度计算 | 预测速度计算 |
---|---|---|---|---|
9/6/20 | 史密斯 | 8 | 85.6 | 在 |
11/15/20 | 史密斯 | 6 | 82.6 | 在 |
1/4/21 | 史密斯 | 7 | 83.4 | 84.1 |
2/20/21 | 史密斯 | 7 | 82.9 | 83.9 |
4/5/21 | 史密斯 | 8.5 | 84.8 | 85.7 |
有另一列具有 predict_speed_calc 的标准误差也很好,但这是我稍后会解决的次要问题。提前感谢您对上述内容的任何指导和建议。
编辑2:
我现在有了滚动线性 OLS 结果的可行函数。但是,如果可能的话,我还想尝试使用“from_formula”方法进行二次多项式拟合,并返回残差以将它们与线性拟合进行比较。
我正在尝试根据此处的信息和下面定义的“speed_preference_from_formula”函数来拟合二次方程。但是,如果我尝试引用同一列两次(即使用 'avg_speed_calc ~ Distance + Distance**2','params' 只返回两列而不是预期的三列。我为平方值创建了一个辅助列(见下文),但返回的系数显然不准确,所以我知道我做错了什么。
import numpy.polynomial.polynomial as poly
import patsy
df['Distance2'] = df['Distance']**2
grouped2 = df.groupby('Name')
form = "avg_speed_calc ~ Distance + Distance2"
params2 = grouped2.apply(lambda x: speed_preference_from_formula(x, form, 4))