Anexar valores y residuos predichos a la estructura de datos de pandas

Es una práctica útil y común agregar valores y residuos pronosticados de la ejecución de una regresión en un dataframe como columnas distintas. Soy nuevo en pandas y tengo problemas para realizar esta operación muy simple. Sé que me falta algo obvio. Hubo una pregunta muy similar sobre hace un año y medio, pero en realidad no fue respondida.

El dataframe actualmente se ve algo como esto:

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 todo lo que quiero es devolver un dataframe que tenga el valor predicho y el residuo de y = x1 + x2 para cada observación:

 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 

He intentado resolver esto usando statsmodels y pandas y no he podido resolverlo. ¡Gracias por adelantado!

Aquí hay una variación de la respuesta de Alexander utilizando el modelo OLS de statsmodels en lugar del modelo de pandas ols. Podemos usar la fórmula o la interfaz array / DataFrame para los modelos.

fittedvalues y resid son series de pandas con el índice correcto. predict no devuelve una serie de pandas.

 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 

Como vista previa, hay un método de predicción extendida en los resultados del modelo en statsmodels master (0.7), pero la API aún no está resuelta:

 >>> 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 

Esto debería ser auto explicativo.

 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 

Por lo tanto, es correcto formular sus preguntas de manera que sea fácil para los contribuyentes ejecutar su código.

 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 

Entonces llamando a df.head() obtiene:

  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 

Ahora, para su pregunta, es bastante sencillo agregar columnas con valores calculados, aunque no estoy de acuerdo con sus datos de muestra:

 df['y_hat'] = df['x1'] + df['x2'] df['res'] = df['y'] - df['y_hat'] 

Para mí, estos rinden:

  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 

¡Espero que esto ayude!