เรียกใช้การถดถอย OLS ด้วย Pandas Data Frame


111

ฉันมีpandasกรอบข้อมูลและต้องการทำนายค่าของคอลัมน์ A จากค่าในคอลัมน์ B และ C นี่คือตัวอย่างของเล่น:

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

ตามหลักการแล้วฉันจะมีบางอย่างที่คล้ายกันols(A ~ B + C, data = df)แต่เมื่อฉันดูตัวอย่างจากไลบรารีอัลกอริทึมscikit-learnดูเหมือนว่าจะฟีดข้อมูลไปยังโมเดลด้วยรายการแถวแทนที่จะเป็นคอลัมน์ สิ่งนี้ทำให้ฉันต้องฟอร์แมตข้อมูลใหม่เป็นรายการภายในลิสต์ซึ่งดูเหมือนจะเอาชนะจุดประสงค์ของการใช้แพนด้าตั้งแต่แรก วิธีใดที่เป็นวิธี pythonic ที่สุดในการเรียกใช้การถดถอย OLS (หรืออัลกอริธึมการเรียนรู้ของเครื่องโดยทั่วไป) กับข้อมูลในกรอบข้อมูลแพนด้า

คำตอบ:


152

ฉันคิดว่าคุณสามารถทำในสิ่งที่คุณคิดว่าเหมาะที่สุดโดยใช้แพ็คเกจstatsmodelsซึ่งเป็นหนึ่งในpandas'การอ้างอิงที่เป็นทางเลือกก่อนpandas' เวอร์ชัน 0.20.0 (ใช้สำหรับบางสิ่ง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
โปรดทราบว่าคีย์เวิร์ดที่ถูกต้องคือformulaฉันพิมพ์formulasผิดโดยไม่ได้ตั้งใจและได้รับข้อผิดพลาดแปลก ๆ :TypeError: from_formula() takes at least 3 arguments (2 given)
denfromufa

@DSM ใหม่มากสำหรับ python พยายามเรียกใช้รหัสเดียวกันของคุณและมีข้อผิดพลาดกับข้อความพิมพ์ทั้งสอง: print result.summary () ^ SyntaxError: ไม่ถูกต้องไวยากรณ์ >>> print result.parmas File "<stdin>", line 1 print result.parmas ^ SyntaxError: ไม่มีวงเล็บใน เรียก 'พิมพ์' ... บางทีฉันโหลดแพ็คเกจผิด ?? ดูเหมือนว่าจะใช้งานได้เมื่อฉันไม่ใส่ "พิมพ์" ขอบคุณ
a.powell

2
@ a.powell รหัสของ OP ใช้สำหรับ Python 2 การเปลี่ยนแปลงเดียวที่ฉันคิดว่าคุณต้องทำคือใส่วงเล็บรอบอาร์กิวเมนต์เพื่อพิมพ์: print(result.params)และprint(result.summary())
Paul Moore

ฉันจะขอบคุณถ้าคุณได้ดูสิ่งนี้และขอขอบคุณ: stackoverflow.com/questions/44923808/…
Desta Haileselassie Hagos

การพยายามใช้formula()วิธีนี้ทำให้เกิดข้อผิดพลาดประเภท TypeError: __init __ () ขาดอาร์กิวเมนต์ตำแหน่งที่ต้องการ 1 รายการ: 'endog' ดังนั้นฉันเดาว่าเลิกใช้แล้ว นอกจากนี้ยังมีolsอยู่ในขณะนี้OLS
3pitt

68

หมายเหตุ: pandas.stats ถูกลบออกด้วย 0.20.0


สามารถทำได้ด้วย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---------------------------------

โปรดทราบว่าคุณต้องstatsmodelsติดตั้งแพคเกจซึ่งจะใช้งานภายในโดยpandas.stats.olsฟังก์ชัน


13
โปรดทราบว่าสิ่งนี้จะถูกยกเลิกในเวอร์ชันอนาคตของแพนด้า!
denfromufa

4
ทำไมถึงทำมัน? ฉันหวังเป็นอย่างยิ่งว่าฟังก์ชันนี้จะคงอยู่! มันมีประโยชน์และรวดเร็วจริงๆ!
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 missing interceptsนี้อาจจะเป็นเพราะมีปัญหากับ นักออกแบบของเทียบเท่าRปรับแพคเกจโดยการเอาการปรับสำหรับความหมาย: stats.stackexchange.com/a/36068/64552 . คำแนะนำอื่น ๆ : you can use sm.add_constant to add an intercept to the exog arrayและใช้คำสั่ง: reg = ols("y ~ x", data=dict(y=y,x=x)).fit()
javadba

2
มันเป็นวันที่น่าเศร้าเมื่อพวกเขาลบpandas.stats💔
3kstc

31

ฉันไม่รู้ว่านี่เป็นของใหม่sklearnหรือpandasแต่ฉันสามารถส่งผ่าน data frame ได้โดยตรงsklearnโดยไม่ต้องแปลง data frame เป็น numpy array หรือประเภทข้อมูลอื่น ๆ

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
การเบี่ยงเบนเล็กน้อยจาก OP - แต่ฉันพบว่าคำตอบนี้มีประโยชน์มากหลังจากต่อท้าย.values.reshape(-1, 1)คอลัมน์ dataframe ตัวอย่างเช่น: x_data = df['x_data'].values.reshape(-1, 1)และส่งอาร์เรย์ np x_data(และสร้างขึ้นในทำนองเดียวกันy_data) ลงใน.fit()เมธอด
S3DEV

16

สิ่งนี้ทำให้ฉันต้องฟอร์แมตข้อมูลใหม่เป็นรายการภายในลิสต์ซึ่งดูเหมือนจะเอาชนะจุดประสงค์ของการใช้แพนด้าตั้งแต่แรก

ไม่ไม่เพียงแค่แปลงเป็นอาร์เรย์ NumPy:

>>> data = np.asarray(df)

การดำเนินการนี้ใช้เวลาคงที่เนื่องจากเพียงแค่สร้างมุมมองข้อมูลของคุณ จากนั้นป้อนให้กับ 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
ฉันต้องทำnp.matrix( np.asarray( df ) )เพราะ sklearn คาดหวังเวกเตอร์แนวตั้งในขณะที่อาร์เรย์ numpy เมื่อคุณตัดมันออกจากอาร์เรย์แล้วให้ทำตัวเหมือน vecotrs แนวนอนซึ่งส่วนใหญ่แล้วจะดีมาก
cjohnson318

ไม่มีวิธีง่ายๆในการทดสอบค่าสัมประสิทธิ์กับเส้นทางนี้
MichaelChirico

2
ไม่มีวิธีให้อาหาร Scikit-Learn โดยตรงกับ Pandas DataFrame หรือไม่?
Femto Trader

สำหรับโมดูล sklearn อื่น ๆ (แผนผังการตัดสินใจ ฯลฯ ) ฉันใช้ค่า df ['colname'] แล้ว แต่ไม่ได้ผลสำหรับสิ่งนี้
szeitlin

1
คุณยังสามารถใช้.valuesแอตทริบิวต์ ได้แก่reg.fit(df[['B', 'C']].values, df['A'].values).
3novak

6

Statsmodels สามารถสร้างโมเดล OLS ที่มีการอ้างอิงคอลัมน์ไปยังดาต้าเฟรมของแพนด้าโดยตรง

สั้นและหวาน:

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


รายละเอียดรหัสและสรุปการถดถอย:

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

เอาท์พุท:

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

วิธีรับ R-squared สัมประสิทธิ์และค่า 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.