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?
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.
Remarque:pandas.stats
a é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
.
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])
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