如何在DataFrame中按观测分组做线性回归并将结果存回对应行(无循环)
无循环实现分组线性回归并合并结果
假设你的数据已加载为 pandas DataFrame(命名为df),以下是无需手动循环的实现方案:
1. 预处理日期为数值自变量
线性回归要求自变量为数值类型,先将Date转换为可计算的数值(这里以日期序数为例,也可根据实际需求用时间差等编码方式):
import pandas as pd # 转换Date为datetime类型,再转为序数数值 df['Date_num'] = pd.to_datetime(df['Date']).apply(lambda x: x.toordinal()) # 若result是字符串格式(如示例中的r1,1),需先转为数值: # df['result'] = df['result'].str.replace('r', '').astype(float)
2. 分组计算回归结果并合并回原表
利用 pandas 的groupby结合apply完成分组回归,再通过合并将结果映射到原表对应行:
import statsmodels.api as sm def extract_reg_stats(group): # 为自变量添加截距项 X = sm.add_constant(group['Date_num']) y = group['result'] # 拟合普通最小二乘回归 model = sm.OLS(y, X).fit() # 返回需要的回归指标(可根据需求调整) return pd.Series({ 'reg_intercept': model.params[0], 'reg_slope': model.params[1], 'reg_r2': model.rsquared }) # 按观测分组计算回归结果 reg_summary = df.groupby('temp').apply(extract_reg_stats).reset_index() # 将回归结果合并回原数据表 final_df = df.merge(reg_summary, on='temp', how='left')
替代方案:使用scikit-learn实现
若你更熟悉scikit-learn工具链,可采用以下代码:
from sklearn.linear_model import LinearRegression from sklearn.metrics import r2_score def sklearn_reg_stats(group): X = group['Date_num'].values.reshape(-1, 1) y = group['result'].values model = LinearRegression().fit(X, y) return pd.Series({ 'reg_intercept': model.intercept_, 'reg_slope': model.coef_[0], 'reg_r2': r2_score(y, model.predict(X)) }) reg_summary_sklearn = df.groupby('temp').apply(sklearn_reg_stats).reset_index() final_df_sklearn = df.merge(reg_summary_sklearn, on='temp', how='left')
关键说明
groupby+apply由pandas内部优化执行,效率远高于手动循环;- 回归结果会自动匹配到对应观测的所有行中,无需额外索引对齐操作;
- 可根据业务需求修改回归指标提取逻辑,比如添加p值、标准误等统计量。
内容的提问来源于stack exchange,提问作者Thierry Donitali
相关产品推荐
相关产品推荐

