将预测值和残差添加到pandas数据框中

7
这是一种有用且常见的做法,将回归预测的值和残差作为不同的列添加到数据帧中。我对pandas不熟悉,无法完成这个非常简单的操作,我知道我缺少了一些显而易见的东西。大约一年半前,有一个非常相似的问题被提出,但并没有得到真正的答案。 数据帧当前看起来像这样:
y               x1           x2   
880.37          3.17         23
716.20          4.76         26
974.79          4.17         73
322.80          8.70         72
1054.25         11.45        16

我想要返回一个数据框,其中包含每个观测值的y = x1 + x2的预测值和残差:

y               x1           x2       y_hat         res
880.37          3.17         23       840.27        40.10
716.20          4.76         26       752.60        -36.40
974.79          4.17         73       877.49        97.30
322.80          8.70         72       348.50        -25.70
1054.25         11.45        16       815.15        239.10

我已经尝试使用statsmodels和pandas来解决这个问题,但是一直没有成功。提前感谢!

3个回答

11
这里是对Alexander的答案进行变化,使用statsmodels中的OLS模型而不是pandas ols模型。我们可以使用公式或数组/DataFrame接口来访问模型。
fittedvalues和resid是带有正确索引的pandas Series。predict不会返回pandas Series。
import numpy as np
import pandas as pd
import statsmodels.api as sm
import statsmodels.formula.api as smf

df = pd.DataFrame({'x1': [3.17, 4.76, 4.17, 8.70, 11.45],
                   'x2': [23, 26, 73, 72, 16],
                   'y': [880.37, 716.20, 974.79, 322.80, 1054.25]},
                   index=np.arange(10, 20, 2))

result = smf.ols('y ~ x1 + x2', df).fit()
df['yhat'] = result.fittedvalues
df['resid'] = result.resid


result2 = sm.OLS(df['y'], sm.add_constant(df[['x1', 'x2']])).fit()
df['yhat2'] = result2.fittedvalues
df['resid2'] = result2.resid

# predict doesn't return pandas series and no index is available
df['predicted'] = result.predict(df)

print(df)

       x1  x2        y        yhat       resid       yhat2      resid2  \
10   3.17  23   880.37  923.949309  -43.579309  923.949309  -43.579309   
12   4.76  26   716.20  890.732201 -174.532201  890.732201 -174.532201   
14   4.17  73   974.79  656.155079  318.634921  656.155079  318.634921   
16   8.70  72   322.80  610.510952 -287.710952  610.510952 -287.710952   
18  11.45  16  1054.25  867.062458  187.187542  867.062458  187.187542   

     predicted  
10  923.949309  
12  890.732201  
14  656.155079  
16  610.510952  
18  867.062458  

作为预览,statsmodels master(0.7)中的模型结果具有扩展预测方法,但API尚未确定。
>>> print(result.get_prediction().summary_frame())
          mean     mean_se  mean_ci_lower  mean_ci_upper  obs_ci_lower  \
10  923.949309  268.931939    -233.171432    2081.070051   -991.466820   
12  890.732201  211.945165     -21.194241    1802.658643   -887.328646   
14  656.155079  269.136102    -501.844105    1814.154263  -1259.791854   
16  610.510952  282.182030    -603.620329    1824.642233  -1339.874985   
18  867.062458  329.017262    -548.584564    2282.709481  -1214.750941   

    obs_ci_upper  
10   2839.365439  
12   2668.793048  
14   2572.102012  
16   2560.896890  
18   2948.875858  

谢谢,这真是帮了我大忙! - Uncle Milton

3
这个应该是不言自明的。
import pandas as pd

df = pd.DataFrame({'x1': [3.17, 4.76, 4.17, 8.70, 11.45],
                   'x2': [23, 26, 73, 72, 16],
                   'y': [880.37, 716.20, 974.79, 322.80, 1054.25]})
model = pd.ols(y=df.y, x=df.loc[:, ['x1', 'x2']])
df['y_hat'] = model.y_fitted
df['res'] = model.resid

>>> df
      x1  x2        y       y_hat         res
0   3.17  23   880.37  923.949309  -43.579309
1   4.76  26   716.20  890.732201 -174.532201
2   4.17  73   974.79  656.155079  318.634921
3   8.70  72   322.80  610.510952 -287.710952
4  11.45  16  1054.25  867.062458  187.187542

这很简单而且更好。 - Rajesh Mappu

1

因此,礼貌的做法是编写问题时使得其他人能够轻松运行你的代码。

import pandas as pd

y_col = [880.37, 716.20, 974.79, 322.80, 1054.25]
x1_col = [3.17, 4.76, 4.17, 8.70, 11.45]
x2_col = [23, 26, 73, 72, 16]

df = pd.DataFrame()
df['y'] = y_col
df['x1'] = x1_col
df['x2'] = x2_col

然后调用df.head()会产生以下结果:
         y     x1  x2
0   880.37   3.17  23
1   716.20   4.76  26
2   974.79   4.17  73
3   322.80   8.70  72
4  1054.25  11.45  16

现在针对您的问题,添加计算值的列相当简单,尽管我不同意您的样本数据:
df['y_hat'] = df['x1'] + df['x2']
df['res'] = df['y'] - df['y_hat']

对我来说,它们产生了以下结果:
         y     x1  x2  y_hat      res
0   880.37   3.17  23  26.17   854.20
1   716.20   4.76  26  30.76   685.44
2   974.79   4.17  73  77.17   897.62
3   322.80   8.70  72  80.70   242.10
4  1054.25  11.45  16  27.45  1026.80

希望这有所帮助!

1
要添加现有列的算术组合列,您还可以执行 df.eval('y_hat = x1 + y1'),这很好,特别是如果您的 DataFrame 名称很长。 - JoeCondron
非常有帮助。将确保在未来添加数据框源代码。谢谢! - Uncle Milton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接