Chạy hồi quy OLS với Khung dữ liệu Pandas


111

Tôi có một pandaskhung dữ liệu và tôi muốn có thể dự đoán giá trị của cột A từ các giá trị trong cột B và C. Đây là một ví dụ đồ chơi:

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

Lý tưởng nhất, tôi sẽ có một cái gì đó giống như ols(A ~ B + C, data = df)nhưng khi tôi xem xét các ví dụ từ các thư viện thuật toán, scikit-learnnó dường như cung cấp dữ liệu cho mô hình với danh sách các hàng thay vì cột. Điều này sẽ yêu cầu tôi định dạng lại dữ liệu thành các danh sách bên trong danh sách, điều này dường như đánh bại mục đích sử dụng gấu trúc ngay từ đầu. Cách khó hiểu nhất để chạy hồi quy OLS (hoặc bất kỳ thuật toán máy học nào nói chung hơn) trên dữ liệu trong khung dữ liệu gấu trúc là gì?

Câu trả lời:


152

Tôi nghĩ rằng bạn gần như có thể làm chính xác những gì bạn nghĩ là lý tưởng, bằng cách sử dụng gói mô hình thống kê , một trong những pandas'phụ thuộc tùy chọn trước pandas' phiên bản 0.20.0 (nó được sử dụng cho một số thứ trong 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
Lưu ý rằng từ khóa đúng là formula, tôi vô tình gõ formulasthay vào đó và nhận lỗi lạ:TypeError: from_formula() takes at least 3 arguments (2 given)
denfromufa

@DSM Rất mới đối với python. Đã thử chạy cùng một mã của bạn và gặp lỗi trên cả hai thông báo in: print result.summary () ^ SyntaxError: cú pháp không hợp lệ >>> print result.parmas Tệp "<stdin>", dòng 1 print result.parmas ^ SyntaxError: Thiếu dấu ngoặc đơn trong gọi đến 'in' ... Có lẽ tôi đã tải các gói sai ?? Nó dường như hoạt động khi tôi không đặt "print". Cảm ơn.
a.powell

2
@ a.powell Mã của OP là dành cho Python 2. Thay đổi duy nhất mà tôi nghĩ bạn cần thực hiện là đặt dấu ngoặc tròn quanh các đối số để in: print(result.params)print(result.summary())
Paul Moore

Tôi sẽ đánh giá cao nếu bạn có thể xem thông tin này và cảm ơn bạn: stackoverflow.com/questions/44923808/…
Desta Haileselassie Hagos,

cố gắng sử dụng formula()phương pháp này sẽ ném ra lỗi loại TypeError: __init __ () thiếu 1 đối số vị trí bắt buộc: 'endog', vì vậy tôi đoán nó không được dùng nữa. cũng, olsbây giờ làOLS
3pitt

68

Lưu ý: pandas.stats đã bị loại bỏ với 0.20.0


Có thể làm điều này với 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---------------------------------

Lưu ý rằng bạn cần phải statsmodelscài đặt gói, gói này được sử dụng trong nội bộ của pandas.stats.olshàm.


13
Lưu ý rằng tính năng này sẽ không được chấp nhận trong phiên bản gấu trúc trong tương lai!
denfromufa

4
Tại sao làm điều đó? Tôi thực sự hy vọng chức năng này tồn tại! Nó THỰC SỰ hữu ích và nhanh chóng!
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. Điều này có thể do vấn đề với missing intercepts. Người thiết kế Rgói tương đương điều chỉnh bằng cách xóa điều chỉnh cho giá trị trung bình: stats.stackexchange.com/a/36068/64552 . . Gợi ý khác: you can use sm.add_constant to add an intercept to the exog arrayvà sử dụng một dict: reg = ols("y ~ x", data=dict(y=y,x=x)).fit()
javadba

2
Đó là một ngày buồn khi họ loại bỏ các pandas.stats💔
3kstc

31

Tôi không biết liệu điều này có mới trong sklearnhay không pandas, nhưng tôi có thể truyền trực tiếp khung dữ liệu đến sklearnmà không cần chuyển đổi khung dữ liệu thành mảng numpy hoặc bất kỳ kiểu dữ liệu nào khác.

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
Sự chuyển hướng nhỏ từ OP - nhưng tôi thấy câu trả lời cụ thể này rất hữu ích, sau khi thêm .values.reshape(-1, 1)vào các cột khung dữ liệu. Ví dụ: x_data = df['x_data'].values.reshape(-1, 1)và truyền x_data(và một y_datamảng np được tạo tương tự ) vào .fit()phương thức.
S3DEV

16

Điều này sẽ yêu cầu tôi định dạng lại dữ liệu thành các danh sách bên trong danh sách, điều này dường như đánh bại mục đích sử dụng gấu trúc ngay từ đầu.

Không, không, chỉ cần chuyển đổi thành mảng NumPy:

>>> data = np.asarray(df)

Điều này mất thời gian liên tục vì nó chỉ tạo một chế độ xem trên dữ liệu của bạn. Sau đó đưa nó vào scikit-learning:

>>> 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
Tôi phải làm như vậy np.matrix( np.asarray( df ) ), bởi vì sklearn mong đợi một vectơ dọc, trong khi các mảng numpy, một khi bạn cắt chúng ra khỏi một mảng, sẽ hoạt động giống như các vecotrs ngang, điều này rất tốt trong hầu hết thời gian.
cjohnson318

không có cách nào đơn giản để làm các xét nghiệm của các hệ số với tuyến đường này, tuy nhiên
MichaelChirico

2
Không có cách nào để cung cấp trực tiếp Scikit-Learn với Pandas DataFrame?
Femto Trader

đối với các mô-đun sklearn khác (cây quyết định, v.v.), tôi đã sử dụng các giá trị df ['colname']., nhưng điều đó không hoạt động cho điều này.
szeitlin

1
Bạn cũng có thể sử dụng .valuesthuộc tính. Tức là reg.fit(df[['B', 'C']].values, df['A'].values),.
3novak

6

Statsmodels kan xây dựng một mô hình OLS với tham chiếu cột trực tiếp đến khung dữ liệu gấu trúc.

Ngắn và ngọt:

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


Chi tiết mã và tóm tắt hồi quy:

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

Đầu ra:

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

Cách lấy trực tiếp R bình phương, Hệ số và giá trị 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.