【问题标题】:Appending predicted values and residuals to pandas dataframe将预测值和残差附加到 pandas 数据帧
【发布时间】:2015-11-13 02:11:36
【问题描述】:

将运行回归的预测值和残差作为不同的列附加到数据框中是一种有用且常见的做法。我是熊猫的新手,我在执行这个非常简单的操作时遇到了麻烦。我知道我遗漏了一些明显的东西。大约一年半前有人问过a very similar question,但没有得到真正的回答。

数据框目前看起来像这样:

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 解决此问题,但无法解决。提前致谢!

【问题讨论】:

    标签: python pandas dataframe prediction statsmodels


    【解决方案1】:

    这是 Alexander 使用 statsmodels 中的 OLS 模型而不是 pandas ols 模型的答案的变体。我们可以对模型使用公式或数组/DataFrame 接口。

    fittedvaluesresid 是具有正确索引的熊猫系列。 predict 不返回熊猫系列。

    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  
    

    【讨论】:

    • 谢谢你,这是一个巨大的帮助!
    【解决方案2】:

    这应该是不言自明的。

    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
    

    【讨论】:

    • 这更简单更好。
    【解决方案3】:

    因此,形成您的问题是礼貌的做法,以便贡献者可以轻松运行您的代码。

    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
    

    希望这会有所帮助!

    【讨论】:

    • 要添加作为现有列的算术组合的列,您也可以使用df.eval('y_hat = x1 + y1'),这很好,尤其是当您的 DataFrame 名称很长时
    • 非常有帮助。将来会确保添加数据框源代码。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 2020-10-22
    • 2018-04-17
    • 2023-04-10
    • 2016-02-09
    • 2015-04-05
    • 2015-12-21
    相关资源
    最近更新 更多