Esegui una regressione OLS con Pandas Data Frame


111

Ho un pandasdata frame e vorrei poter prevedere i valori della colonna A dai valori nelle colonne B e C.Ecco un esempio di giocattolo:

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

Idealmente, avrei qualcosa di simile, ols(A ~ B + C, data = df)ma quando guardo gli esempi dalle librerie di algoritmi come scikit-learnsembra che fornisca i dati al modello con un elenco di righe anziché di colonne. Ciò richiederebbe di riformattare i dati in elenchi all'interno di elenchi, il che sembra vanificare lo scopo dell'uso dei panda in primo luogo. Qual è il modo più pitonico per eseguire una regressione OLS (o qualsiasi algoritmo di apprendimento automatico più in generale) sui dati in un frame di dati panda?

Risposte:


152

Penso che tu possa quasi fare esattamente quello che pensavi fosse l'ideale, usando il pacchetto statsmodels che era una delle pandas"dipendenze opzionali prima pandas" della versione 0.20.0 (era usato per alcune cose in 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
Nota che la parola chiave corretta è formula, invece ho digitato accidentalmente formulase ho ricevuto uno strano errore:TypeError: from_formula() takes at least 3 arguments (2 given)
denfromufa

@DSM Molto nuovo in Python. Ho provato a eseguire lo stesso codice e ho ricevuto errori su entrambi i messaggi di stampa: print result.summary () ^ SyntaxError: invalid syntax >>> print result.parmas File "<stdin>", line 1 print result.parmas ^ SyntaxError: Missing parentheses in chiama a 'print' ... Forse ho caricato i pacchetti male ?? Sembra funzionare quando non metto "print". Grazie.
Power

2
@ a.powell Il codice dell'OP è per Python 2. L'unica modifica che penso che devi fare è mettere parentesi intorno agli argomenti da stampare: print(result.params)eprint(result.summary())
Paul Moore

Gradirei se si potrebbe avere uno sguardo a questo e grazie: stackoverflow.com/questions/44923808/...
Desta Haileselassie Hagos

il tentativo di utilizzare questo formula()approccio genera l'errore di tipo TypeError: __init __ () manca 1 argomento posizionale richiesto: 'endog', quindi immagino che sia deprecato. inoltre, olsora èOLS
3pitt

68

Nota: pandas.stats è stato rimosso con 0.20.0


È possibile farlo con 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---------------------------------

Nota che devi avere il statsmodelspacchetto installato, è usato internamente dalla pandas.stats.olsfunzione.


13
Nota che questo sarà deprecato nella versione futura dei panda!
denfromufa

4
Perché lo fai? Spero vivamente che questa funzione sopravviva! È VERAMENTE utile e veloce!
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. Ciò potrebbe essere dovuto a un problema con missing intercepts. Il progettista del Rpacchetto equivalente esegue la correzione rimuovendo la regolazione per la media: stats.stackexchange.com/a/36068/64552 . . Altri suggerimenti: you can use sm.add_constant to add an intercept to the exog arraye usa un dict: reg = ols("y ~ x", data=dict(y=y,x=x)).fit()
javadba

2
È stato un giorno triste quando hanno rimosso il pandas.stats💔
3kstc

31

Non so se questo sia nuovo in sklearno pandas, ma sono in grado di passare direttamente il frame di dati sklearnsenza convertire il frame di dati in un array numpy o altri tipi di dati.

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
Piccola deviazione dall'OP - ma ho trovato questa particolare risposta molto utile, dopo averla aggiunta .values.reshape(-1, 1)alle colonne del dataframe. Ad esempio: x_data = df['x_data'].values.reshape(-1, 1)e passando gli array np x_data(e creati in modo simile y_data) nel .fit()metodo.
S3DEV

16

Ciò richiederebbe di riformattare i dati in elenchi all'interno di elenchi, il che sembra vanificare lo scopo dell'uso dei panda in primo luogo.

No, basta convertire in un array NumPy:

>>> data = np.asarray(df)

Ciò richiede tempo costante perché crea solo una visualizzazione dei dati. Quindi nutrilo per 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
Ho dovuto farlo np.matrix( np.asarray( df ) ), perché sklearn si aspettava un vettore verticale, mentre gli array numpy, una volta tagliati fuori da un array, si comportano come vecotrs orizzontali, il che è ottimo per la maggior parte del tempo.
cjohnson318

nessun modo semplice per fare le prove dei coefficienti con questa via, però
MichaelChirico

2
Non c'è un modo per alimentare direttamente Scikit-Learn con Pandas DataFrame?
Femto Trader

per altri moduli sklearn (albero decisionale, ecc.), ho usato i valori df ['colname']., ma non ha funzionato per questo.
szeitlin

1
Puoi anche usare l' .valuesattributo. Vale a dire, reg.fit(df[['B', 'C']].values, df['A'].values).
3novak

6

Statsmodels può costruire un modello OLS con riferimenti di colonna direttamente a un dataframe pandas.

Breve e dolce:

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


Dettagli del codice e riepilogo della regressione:

# 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()

Produzione:

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

Come ottenere direttamente R quadrato, coefficienti e valore p:

# 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.