Jalankan regresi OLS dengan Pandas Data Frame

111

Saya memiliki pandaskerangka data dan saya ingin dapat memprediksi nilai kolom A dari nilai di kolom B dan C. Berikut adalah contoh mainannya:

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

Idealnya, saya akan memiliki sesuatu seperti ols(A ~ B + C, data = df)tetapi ketika saya melihat contoh dari perpustakaan algoritma seperti scikit-learnitu tampaknya memberi makan data ke model dengan daftar baris, bukan kolom. Ini akan mengharuskan saya untuk memformat ulang data menjadi daftar di dalam daftar, yang tampaknya menggagalkan tujuan penggunaan panda sejak awal. Apa cara paling pythonic untuk menjalankan regresi OLS (atau algoritme pembelajaran mesin apa pun secara lebih umum) pada data dalam bingkai data pandas?

Michael
sumber

Jawaban:

152

Saya pikir Anda hampir dapat melakukan apa yang Anda pikir akan ideal, menggunakan paket statsmodels yang merupakan salah satu pandas'dependensi opsional sebelum pandas' versi 0.20.0 (itu digunakan untuk beberapa hal 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.
DSM
sumber
2
Perhatikan bahwa kata kunci yang benar adalah formula, saya tidak sengaja mengetik formulasdan mendapat kesalahan aneh:TypeError: from_formula() takes at least 3 arguments (2 given)
denfromufa
@DSM Sangat baru mengenal python. Mencoba menjalankan kode yang sama dan mendapatkan kesalahan pada kedua pesan cetak: print result.summary () ^ SyntaxError: sintaks tidak valid >>> print result.parmas File "<stdin>", baris 1 print result.parmas ^ SyntaxError: Tanda kurung tidak ada di panggilan untuk 'mencetak' ... Mungkin saya salah memuat paket ?? Tampaknya berfungsi jika saya tidak meletakkan "print". Terima kasih.
a.powell
2
@ a.powell Kode OP untuk Python 2. Satu-satunya perubahan yang menurut saya perlu Anda lakukan adalah meletakkan tanda kurung di sekitar argumen untuk dicetak: print(result.params)danprint(result.summary())
Paul Moore
Saya akan sangat menghargai jika Anda dapat melihat ini dan terima kasih: stackoverflow.com/questions/44923808/…
Desta Haileselassie Hagos
mencoba untuk menggunakan formula()pendekatan ini melempar kesalahan jenis TypeError: __init __ () kehilangan 1 argumen posisi yang diperlukan: 'endog', jadi saya rasa itu sudah usang. juga, olssekarangOLS
3pitt
68

Catatan: pandas.stats telah dihapus dengan 0.20.0


Ini mungkin dilakukan dengan 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---------------------------------

Perhatikan bahwa Anda perlu statsmodelsmenginstal paket, ini digunakan secara internal oleh pandas.stats.olsfungsi.

Roman Pekar
sumber
13
Perhatikan bahwa ini akan dihentikan pada versi panda yang akan datang!
denfromufa
4
Mengapa melakukannya? Saya sangat berharap fungsi ini bertahan! Ini SANGAT berguna dan cepat!
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
@DestaHaselas Ini mungkin karena masalah dengan missing intercepts. Perancang Rpaket yang setara menyesuaikan dengan menghapus penyesuaian untuk mean: stats.stackexchange.com/a/36068/64552 . . Saran lain: you can use sm.add_constant to add an intercept to the exog arraydan gunakan reg = ols("y ~ x", data=dict(y=y,x=x)).fit()
dikt
2
Itu adalah hari yang menyedihkan ketika mereka menghapus pandas.stats💔
3kstc
31

Saya tidak tahu apakah ini baru di sklearnatau pandas, tetapi saya dapat meneruskan bingkai data secara langsung ke sklearntanpa mengubah bingkai data ke array numpy atau tipe data lainnya.

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])
3novak
sumber
2
Pengalihan kecil dari OP - tetapi saya menemukan jawaban khusus ini sangat membantu, setelah menambahkan .values.reshape(-1, 1)ke kolom dataframe. Misalnya: x_data = df['x_data'].values.reshape(-1, 1)dan meneruskan larik np x_data(dan yang dibuat serupa y_data) ke dalam .fit()metode.
S3DEV
16

Ini akan mengharuskan saya untuk memformat ulang data menjadi daftar di dalam daftar, yang tampaknya menggagalkan tujuan penggunaan panda sejak awal.

Tidak, tidak, cukup ubah ke array NumPy:

>>> data = np.asarray(df)

Ini membutuhkan waktu yang konstan karena hanya membuat file tampilan pada data Anda. Kemudian beri makan ke 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
Fred Foo
sumber
3
Saya harus melakukannya np.matrix( np.asarray( df ) ), karena sklearn mengharapkan vektor vertikal, sedangkan array numpy, setelah Anda memotongnya dari array, bertindak seperti vecotrs horizontal, yang paling bagus sepanjang waktu.
cjohnson318
tidak ada cara sederhana untuk melakukan tes koefisien dengan rute ini, namun
MichaelChirico
2
Apakah tidak ada cara untuk memberi makan Scikit-Learn dengan Pandas DataFrame secara langsung?
Femto Trader
untuk modul sklearn lainnya (pohon keputusan, dll), saya telah menggunakan nilai df ['colname']., tetapi itu tidak berhasil untuk ini.
szeitlin
1
Anda juga bisa menggunakan .valuesatribut tersebut. Yaitu reg.fit(df[['B', 'C']].values, df['A'].values),.
3novak
6

Statsmodels kan membuat model OLS dengan referensi kolom langsung ke kerangka data panda.

Pendek dan manis:

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


Detail kode dan ringkasan regresi:

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

Keluaran:

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

Cara langsung mendapatkan R-squared, Coefficients dan p-value:

# 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
Vestland
sumber