web-dev-qa-db-fra.com

Exécuter une régression OLS avec Pandas Dataframe

J'ai un cadre de données pandas et j'aimerais pouvoir prédire les valeurs de la colonne A à partir des valeurs des colonnes B et C. Voici un exemple de jouet:

import pandas as pd
df = pd.DataFrame({"A": [10,20,30,40,50], 
                   "B": [20, 30, 10, 40, 50], 
                   "C": [32, 234, 23, 23, 42523]})

Idéalement, j'aurais quelque chose comme ols(A ~ B + C, data = df) mais lorsque je regarde les exemples dans des bibliothèques d'algorithmes comme scikit-learn, il semble que les données du modèle soient alimentées avec une liste de lignes plutôt que de colonnes. Cela nécessiterait que je reformate les données dans des listes à l'intérieur de listes, ce qui semble aller à l'encontre de l'objectif d'utiliser des pandas en premier lieu. Quel est le moyen le plus pythonique d’exécuter une régression OLS (ou plus généralement un algorithme d’apprentissage automatique) sur des données d’une trame de données de pandas? 

95
Michael

Je pense que vous pouvez presque faire exactement ce que vous pensiez être idéal, en utilisant le paquet statsmodels qui était l’un des pandas 'dépendances optionnelles avant pandas' version 0.20.0 (il a été utilisé pour quelques opérations dans pandas.stats.)

>>> import pandas as pd
>>> import statsmodels.formula.api as sm
>>> df = pd.DataFrame({"A": [10,20,30,40,50], "B": [20, 30, 10, 40, 50], "C": [32, 234, 23, 23, 42523]})
>>> result = sm.ols(formula="A ~ B + C", data=df).fit()
>>> print result.params
Intercept    14.952480
B             0.401182
C             0.000352
dtype: float64
>>> print result.summary()
                            OLS Regression Results                            
==============================================================================
Dep. Variable:                      A   R-squared:                       0.579
Model:                            OLS   Adj. R-squared:                  0.158
Method:                 Least Squares   F-statistic:                     1.375
Date:                Thu, 14 Nov 2013   Prob (F-statistic):              0.421
Time:                        20:04:30   Log-Likelihood:                -18.178
No. Observations:                   5   AIC:                             42.36
Df Residuals:                       2   BIC:                             41.19
Df Model:                           2                                         
==============================================================================
                 coef    std err          t      P>|t|      [95.0% Conf. Int.]
------------------------------------------------------------------------------
Intercept     14.9525     17.764      0.842      0.489       -61.481    91.386
B              0.4012      0.650      0.617      0.600        -2.394     3.197
C              0.0004      0.001      0.650      0.583        -0.002     0.003
==============================================================================
Omnibus:                          nan   Durbin-Watson:                   1.061
Prob(Omnibus):                    nan   Jarque-Bera (JB):                0.498
Skew:                          -0.123   Prob(JB):                        0.780
Kurtosis:                       1.474   Cond. No.                     5.21e+04
==============================================================================

Warnings:
[1] The condition number is large, 5.21e+04. This might indicate that there are
strong multicollinearity or other numerical problems.
129
DSM

Remarque:pandas.statsa été supprimé avec 0.20.0


Il est possible de faire cela avec pandas.stats.ols:

>>> from pandas.stats.api import ols
>>> df = pd.DataFrame({"A": [10,20,30,40,50], "B": [20, 30, 10, 40, 50], "C": [32, 234, 23, 23, 42523]})
>>> res = ols(y=df['A'], x=df[['B','C']])
>>> res
-------------------------Summary of Regression Analysis-------------------------

Formula: Y ~ <B> + <C> + <intercept>

Number of Observations:         5
Number of Degrees of Freedom:   3

R-squared:         0.5789
Adj R-squared:     0.1577

Rmse:             14.5108

F-stat (2, 2):     1.3746, p-value:     0.4211

Degrees of Freedom: model 2, resid 2

-----------------------Summary of Estimated Coefficients------------------------
      Variable       Coef    Std Err     t-stat    p-value    CI 2.5%   CI 97.5%
--------------------------------------------------------------------------------
             B     0.4012     0.6497       0.62     0.5999    -0.8723     1.6746
             C     0.0004     0.0005       0.65     0.5826    -0.0007     0.0014
     intercept    14.9525    17.7643       0.84     0.4886   -19.8655    49.7705
---------------------------------End of Summary---------------------------------

Notez que le paquetage statsmodels doit être installé. Il est utilisé en interne par la fonction pandas.stats.ols.

63
Roman Pekar

Je ne sais pas s'il s'agit d'une nouveauté dans sklearn ou pandas, mais je peux passer le cadre de données directement à sklearn sans le convertir en un tableau numpy ou tout autre type de données.

from sklearn import linear_model

reg = linear_model.LinearRegression()
reg.fit(df[['B', 'C']], df['A'])

>>> reg.coef_
array([  4.01182386e-01,   3.51587361e-04])
23
3novak

Cela nécessiterait que je reformate les données dans des listes à l'intérieur de listes, ce qui semble aller à l'encontre de l'objectif d'utiliser des pandas en premier lieu.

Non, convertissez-le simplement en tableau NumPy:

>>> data = np.asarray(df)

Cela prend un temps constant, car cela crée simplement un view sur vos données. Puis alimentez-le pour scikit-learn:

>>> from sklearn.linear_model import LinearRegression
>>> lr = LinearRegression()
>>> X, y = data[:, 1:], data[:, 0]
>>> lr.fit(X, y)
LinearRegression(copy_X=True, fit_intercept=True, normalize=False)
>>> lr.coef_
array([  4.01182386e-01,   3.51587361e-04])
>>> lr.intercept_
14.952479503953672
15
Fred Foo