问题描述
希望你一切都好。
我目前正在尝试计算某个数据框组的回归,但没有成功。我正在成功计算我想要的,但由于 out 数据结构,我真的不知道如何将结果重新集成到我的原始数据帧中。我尝试了 2 个功能。
我成功了五分之一并给你代码。
抱歉这条消息的篇幅太大,但我会尽量做到最清楚。
包装
import pandas as pd
from collections import OrderedDict
import statsmodels.api as sm
import numpy as np
from sklearn.linear_model import LinearRegression
def regress(data,yvar,xvars):
Y = data[yvar]
X = data[xvars]
X['intercept'] = 1.
result = sm.OLS(Y,X).fit()
y_pred = result.predict()
residual = Y - y_pred
return residual
def Reg_func(x,y):
# Cross Sectional Regression
x = np.array(x).reshape((-1,1))
y = np.array(y)
model = LinearRegression().fit(x,y)
y_pred = model.intercept_ + np.sum(model.coef_ * x,axis=1)
residual = y - y_pred
return residual
数据框创建
ind = ['I1','I2','I3','I4','I5','I6','I7','I8','I9','I10','I11','I12','I13','I14','I15','I16','I17','I18','I19','I20']
Axe = ['A','A','B','B']
df = pd.DataFrame(np.random.randn(20,2),index = ind,columns=['C1','C2'])
df.insert(0,'Axe',Axe)
计算
# Quintile groupé par Axe
QC1 = df.groupby(['Axe'])['C1'].apply(lambda x: pd.qcut(x,5,labels=False)+1)
print(QC1)
QC1 尊重 df 结构,然后很容易将结果整合到 df
# Simple regression without groupby
res_reg = Reg_func(newdf['C1'],newdf['C2'])
Res_REg 对 df 结构没问题
# Regression per group with Reg_func fucntion
res_reg_group = (df.groupby('Axe').apply(lambda x: Reg_func(x['C1'],x['C2'])))
print(res_reg_group)
由于它的结构,我真的不知道如何将结果重新整合到 df 中
# Regression per group with regress function
res_reg_group2 = df.groupby('Axe').apply(regress,'C1',['C2'])
print(res_reg_group2)
res_reg_group2 似乎有更好的结构(保持索引),但不确定如何将它与我的 df 数据帧结合起来。此外,这个函数 regress 不适用于简单的回归(没有 groupby)。
感谢您的帮助和照顾
解决方法
无索引
在您的第一种情况下,您可以为每个组分别检索残差,例如res_reg_group['A']
。
残差的顺序应该保留(尽管您可能需要仔细检查),在这种情况下,您可以根据它们的分组将它们放入一个新列中:
res_reg_group = (df.groupby('Axe').apply(lambda x: Reg_func(x['C1'],x['C2'])))
df.loc[df['Axe']=='A','res'] = res_reg_group['A']
df.loc[df['Axe']=='B','res'] = res_reg_group['B']
print(df)
Axe C1 C2 res
I1 A 1.624345 -0.611756 0.545826
I2 A -0.528172 -1.072969 -0.943326
I3 B 0.865408 -2.301539 -1.889825
I4 A 1.744812 -0.761207 0.453904
I5 A 0.319039 -0.249370 0.284860
I6 A 1.462108 -2.060141 -0.980035
I7 A -0.322417 -0.384054 -0.156153
I8 B 1.133769 -1.099891 -0.656326
I9 A -0.172428 -0.877858 -0.578330
I10 A 0.042214 0.582815 0.984847
I11 A -1.100619 1.144724 1.000992
I12 B 0.901591 0.502494 0.918503
I13 B 0.900856 -0.683728 -0.267807
I14 A -0.122890 -0.935769 -0.612584
I15 B -0.267888 0.530355 0.807559
I16 B -0.691661 -0.396754 -0.169848
I17 B -0.687173 -0.845206 -0.617767
I18 B -0.671246 -0.012665 0.216664
I19 B -1.117310 0.234416 0.410802
I20 B 1.659802 0.742044 1.248044
带索引
在第二种情况下,您有一个索引可以使用,因此您可以使用公共索引合并两个数据帧:
res_reg_group2 = df.groupby('Axe').apply(regress,'C1',['C2'])
output = df.merge(res_reg_group2.droplevel(0),left_index=True,right_index=True,suffixes=['','_res'])
print(output)
Axe C1 C2 C1_res
I1 A 1.624345 -0.611756 1.277757
I2 A -0.528172 -1.072969 -1.143578
I3 B 0.865408 -2.301539 0.403997
I4 A 1.744812 -0.761207 1.311116
I5 A 0.319039 -0.249370 0.183668
I6 A 1.462108 -2.060141 0.271328
I7 A -0.322417 -0.384054 -0.536289
I8 B 1.133769 -1.099891 0.830338
I9 A -0.172428 -0.877858 -0.674114
I10 A 0.042214 0.582815 0.391883
I11 A -1.100619 1.144724 -0.423441
I12 B 0.901591 0.502494 0.808824
I13 B 0.900856 -0.683728 0.652137
I14 A -0.122890 -0.935769 -0.658330
I15 B -0.267888 0.530355 -0.356992
I16 B -0.691661 -0.396754 -0.902651
I17 B -0.687173 -0.845206 -0.957121
I18 B -0.671246 -0.012665 -0.831740
I19 B -1.117310 0.234416 -1.245321
I20 B 1.659802 0.742044 1.598529
我不确定为什么残差值不同,也许 statsmodels 和 sklearn 之间存在一些差异,但这就是您组合结果的方式