Führen Sie eine OLS-Regression mit Pandas Data Frame aus


111

Ich habe einen pandasDatenrahmen und möchte die Werte von Spalte A aus den Werten in den Spalten B und C vorhersagen können. Hier ein Spielzeugbeispiel:

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]})

Im Idealfall hätte ich so etwas wie, ols(A ~ B + C, data = df)aber wenn ich mir die Beispiele aus Algorithmusbibliotheken ansehe scikit-learn, scheinen die Daten dem Modell mit einer Liste von Zeilen anstelle von Spalten zuzuführen. Dies würde erfordern, dass ich die Daten in Listen innerhalb von Listen umformatiere, was den Zweck der Verwendung von Pandas in erster Linie zu vereiteln scheint. Was ist die pythonischste Methode, um eine OLS-Regression (oder einen Algorithmus für maschinelles Lernen im Allgemeinen) für Daten in einem Pandas-Datenrahmen auszuführen?

Antworten:


152

Ich denke, Sie können fast genau das tun, was Sie für ideal hielten, indem Sie das Paket statsmodels verwenden , das eine der pandasoptionalen Abhängigkeiten vor pandasVersion 0.20.0 war (es wurde für einige Dinge in verwendet 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.

2
Beachten Sie, dass das richtige Schlüsselwort lautet formula: Ich habe formulasstattdessen versehentlich getippt und einen seltsamen Fehler erhalten:TypeError: from_formula() takes at least 3 arguments (2 given)
denfromufa

@DSM Sehr neu in Python. Es wurde versucht, denselben Code auszuführen, und es wurden Fehler in beiden Drucknachrichten angezeigt: print result.summary () ^ SyntaxError: ungültige Syntax >>> print result.parmas Datei "<stdin>", Zeile 1 print result.parmas ^ SyntaxError: Fehlende Klammern in Aufruf zum 'Drucken' ... Vielleicht habe ich Pakete falsch geladen? Es scheint zu funktionieren, wenn ich nicht "drucken" setze. Vielen Dank.
a.powell

2
@ a.powell Der OP-Code ist für Python 2. Die einzige Änderung, die Sie meiner Meinung nach vornehmen müssen, besteht darin, die zu druckenden Argumente in Klammern zu setzen: print(result.params)undprint(result.summary())
Paul Moore

Ich würde mich freuen, wenn Sie sich das ansehen könnten und danke: stackoverflow.com/questions/44923808/…
Desta Haileselassie Hagos

formula()Wenn Sie versuchen, diesen Ansatz zu verwenden, wird der Typfehler TypeError: __init __ () ausgelöst. Es fehlt ein erforderliches Positionsargument: 'endog'. Ich denke, es ist veraltet. auch olsist jetztOLS
3pitt

68

Hinweis: pandas.stats wurde mit 0.20.0 entfernt


Dies ist möglich mit 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---------------------------------

Beachten Sie, dass das statsmodelsPaket installiert sein muss. Es wird intern von der pandas.stats.olsFunktion verwendet.


13
Beachten Sie, dass dies in zukünftigen Versionen von Pandas veraltet sein wird!
Denfromufa

4
Warum machst du das? Ich hoffe sehr, dass diese Funktion überlebt! Es ist wirklich nützlich und schnell!
FaCoffee

2
The pandas.stats.ols module is deprecated and will be removed in a future version. We refer to external packages like statsmodels, see some examples here: http://www.statsmodels.org/stable/regression.html
Javadba

2
@DestaHaileselassieHagos. Dies kann auf ein Problem mit zurückzuführen sein missing intercepts. Der Designer des entsprechenden RPakets passt sich an, indem er die Anpassung für den Mittelwert entfernt: stats.stackexchange.com/a/36068/64552 . . Andere Vorschläge: you can use sm.add_constant to add an intercept to the exog arrayund verwenden Sie ein Diktat: reg = ols("y ~ x", data=dict(y=y,x=x)).fit()
Javadba

2
Es war ein trauriger Tag, als sie die pandas.stats💔
3kstc

31

Ich weiß nicht, ob dies neu in sklearnoder ist pandas, aber ich kann den sklearnDatenrahmen direkt an übergeben, ohne den Datenrahmen in ein Numpy-Array oder einen anderen Datentyp zu konvertieren.

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

2
Kleine Ablenkung vom OP - aber ich fand diese spezielle Antwort sehr hilfreich, nachdem ich sie .values.reshape(-1, 1)an die Datenrahmenspalten angehängt hatte. Zum Beispiel: x_data = df['x_data'].values.reshape(-1, 1)und Übergeben der x_data(und eines ähnlich erstellten y_data) np-Arrays an die .fit()Methode.
S3DEV

16

Dies würde erfordern, dass ich die Daten in Listen innerhalb von Listen umformatiere, was den Zweck der Verwendung von Pandas in erster Linie zu vereiteln scheint.

Nein, nicht in ein NumPy-Array konvertieren:

>>> data = np.asarray(df)

Dies nimmt eine konstante Zeit in Anspruch, da nur eine Ansicht Ihrer Daten erstellt wird. Dann füttere es an 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

3
Ich musste es tun np.matrix( np.asarray( df ) ), weil sklearn einen vertikalen Vektor erwartete, während numpy Arrays, sobald Sie sie von einem Array abschneiden, wie horizontale Vecotrs wirken, was die meiste Zeit großartig ist.
cjohnson318

Es gibt jedoch keine einfache Möglichkeit, die Koeffizienten mit dieser Route zu
testen

2
Gibt es nicht eine Möglichkeit, Scikit-Learn direkt mit Pandas DataFrame zu füttern?
Femto Trader

Für andere sklearn-Module (Entscheidungsbaum usw.) habe ich df ['colname']. -Werte verwendet, aber das hat hier nicht funktioniert.
szeitlin

1
Sie können auch das .valuesAttribut verwenden. Dh reg.fit(df[['B', 'C']].values, df['A'].values).
3novak

6

Statistikmodelle können ein OLS-Modell mit Spaltenverweisen direkt auf einen Pandas-Datenrahmen erstellen.

Kurz und bündig:

model = sm.OLS(df[y], df[x]).fit()


Codedetails und Regressionszusammenfassung:

# imports
import pandas as pd
import statsmodels.api as sm
import numpy as np

# data
np.random.seed(123)
df = pd.DataFrame(np.random.randint(0,100,size=(100, 3)), columns=list('ABC'))

# assign dependent and independent / explanatory variables
variables = list(df.columns)
y = 'A'
x = [var for var in variables if var not in y ]

# Ordinary least squares regression
model_Simple = sm.OLS(df[y], df[x]).fit()

# Add a constant term like so:
model = sm.OLS(df[y], sm.add_constant(df[x])).fit()

model.summary()

Ausgabe:

                            OLS Regression Results                            
==============================================================================
Dep. Variable:                      A   R-squared:                       0.019
Model:                            OLS   Adj. R-squared:                 -0.001
Method:                 Least Squares   F-statistic:                    0.9409
Date:                Thu, 14 Feb 2019   Prob (F-statistic):              0.394
Time:                        08:35:04   Log-Likelihood:                -484.49
No. Observations:                 100   AIC:                             975.0
Df Residuals:                      97   BIC:                             982.8
Df Model:                           2                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
const         43.4801      8.809      4.936      0.000      25.996      60.964
B              0.1241      0.105      1.188      0.238      -0.083       0.332
C             -0.0752      0.110     -0.681      0.497      -0.294       0.144
==============================================================================
Omnibus:                       50.990   Durbin-Watson:                   2.013
Prob(Omnibus):                  0.000   Jarque-Bera (JB):                6.905
Skew:                           0.032   Prob(JB):                       0.0317
Kurtosis:                       1.714   Cond. No.                         231.
==============================================================================

So erhalten Sie direkt R-Quadrat, Koeffizienten und p-Wert:

# commands:
model.params
model.pvalues
model.rsquared

# demo:
In[1]: 
model.params
Out[1]:
const    43.480106
B         0.124130
C        -0.075156
dtype: float64

In[2]: 
model.pvalues
Out[2]: 
const    0.000003
B        0.237924
C        0.497400
dtype: float64

Out[3]:
model.rsquared
Out[2]:
0.0190
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.