熊猫数据框分组和回归计算

时间:2021-03-10 10:22:05

标签: python pandas dataframe group-by regression

希望你一切都好。

我目前正在尝试计算某个数据框组的回归,但没有成功。我正在成功计算我想要的,但由于 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', 'A', 'A', 'A', 'A', 'B', 'A', 'A', 'A', 'B', 'B', 'A', 'B', 'B', 'B', 'B', '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)。

感谢您的帮助和照顾

1 个答案:

答案 0 :(得分:0)

无索引

在您的第一种情况下,您可以为每个组分别检索残差,例如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 之间存在一些差异,但这就是您组合结果的方式