Uruchom regresję OLS z ramką danych Pandas

111

Mam pandasramkę danych i chciałbym móc przewidzieć wartości kolumny A na podstawie wartości w kolumnach B i C. Oto przykład zabawki:

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

Najlepiej byłoby, gdybyś miał coś takiego, ols(A ~ B + C, data = df)ale kiedy patrzę na przykłady z bibliotek algorytmów scikit-learn, wydaje się, że przekazuje dane do modelu z listą wierszy zamiast kolumn. Wymagałoby to ode mnie ponownego sformatowania danych w listy wewnątrz list, co wydaje się przede wszystkim zniweczyć cel używania pand. Jaki jest najbardziej pythonowy sposób uruchamiania regresji OLS (lub bardziej ogólnie dowolnego algorytmu uczenia maszynowego) na danych w ramce danych pandy?

Michael
źródło

Odpowiedzi:

152

Myślę, że możesz zrobić prawie dokładnie to, co uważałeś za idealne, używając pakietu statsmodels , który był jedną z `` pandasopcjonalnych zależności przed pandas'' wersją 0.20.0 (był używany do kilku rzeczy 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
źródło
2
Zauważ, że prawidłowe słowo kluczowe to formula, przypadkowo formulasTypeError: from_formula() takes at least 3 arguments (2 given)
wpisałem
@DSM Bardzo nowy w Pythonie. Próbowałem uruchomić ten sam kod i otrzymałem błędy w obu komunikatach drukowania: print result.summary () ^ SyntaxError: nieprawidłowa składnia >>> print result.parmas Plik "<stdin>", wiersz 1 wypisuje wynik.parmas ^ SyntaxError: Brak nawiasów w wywołanie 'print' ... Może źle załadowałem paczki? Wygląda na to, że działa, gdy nie umieszczam słowa „drukuj”. Dzięki.
a.powell
2
@ a.powell Kod OP jest przeznaczony dla Pythona 2. Jedyną zmianą, którą myślę, że musisz wprowadzić, jest umieszczenie nawiasów wokół argumentów do wydrukowania: print(result.params)iprint(result.summary())
Paul Moore
Byłbym wdzięczny, gdybyś mógł
rzucić
próba użycia tego formula()podejścia generuje błąd typu TypeError: __init __ () brakuje 1 wymaganego argumentu pozycyjnego: „endog”, więc wydaje mi się, że jest on przestarzały. również olsjest terazOLS
3pitt
68

Uwaga: pandas.stats została usunięta w wersji 0.20.0


Można to zrobić za pomocą 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---------------------------------

Zauważ, że musisz mieć statsmodelszainstalowany pakiet, jest on używany wewnętrznie przez pandas.stats.olsfunkcję.

Roman Pekar
źródło
13
Zwróć uwagę, że w przyszłych wersjach pandy zostanie to wycofane!
denfromufa
4
Dlaczego to robisz? Mam wielką nadzieję, że ta funkcja przetrwa! To NAPRAWDĘ przydatne i szybkie!
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. Może to być spowodowane problemem missing intercepts. Projektant Rpakietu równoważnego dostosowuje się, usuwając korektę dla średniej: stats.stackexchange.com/a/36068/64552 . . Inne sugestie: you can use sm.add_constant to add an intercept to the exog arrayi użyj reg = ols("y ~ x", data=dict(y=y,x=x)).fit()
dyktatu
2
To był smutny dzień, kiedy usunęli pandas.stats💔
3kstc
31

Nie wiem, czy jest to nowe w programie sklearnlub pandas, ale jestem w stanie przekazać ramkę danych bezpośrednio do sklearnbez konwertowania ramki danych na tablicę numpy lub jakiekolwiek inne typy danych.

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
źródło
2
Małe odejście od PO - ale uważam, że ta konkretna odpowiedź jest bardzo pomocna po dołączeniu .values.reshape(-1, 1)do kolumn ramki danych. Na przykład: x_data = df['x_data'].values.reshape(-1, 1)i przekazanie x_data(i podobnie utworzonych y_data) tablic np do .fit()metody.
S3DEV
16

Wymagałoby to ode mnie ponownego sformatowania danych w listy wewnątrz list, co wydaje się przede wszystkim zniweczyć cel używania pand.

Nie, po prostu przekonwertuj na tablicę NumPy:

>>> data = np.asarray(df)

Zajmuje to ciągły czas, ponieważ tworzy tylko widok danych. Następnie nakarm go, aby nauczyć się scikit:

>>> 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
źródło
3
Musiałem to zrobić np.matrix( np.asarray( df ) ), ponieważ sklearn spodziewał się wektora pionowego, podczas gdy tablice numpy, po odcięciu ich od tablicy, działają jak poziome vecotry, co jest świetne przez większość czasu.
cjohnson318
nie ma jednak prostego sposobu na sprawdzenie współczynników tą drogą
MichaelChirico
2
Czy nie ma sposobu, aby bezpośrednio zasilić Scikit-Learn za pomocą Pandas DataFrame?
Femto Trader
dla innych modułów sklearn (drzewo decyzyjne itp.) użyłem wartości df ['colname']., ale to nie zadziałało.
szeitlin
1
Możesz również użyć .valuesatrybutu. Tj reg.fit(df[['B', 'C']].values, df['A'].values).
3novak
6

Statsmodels kan tworzy model OLS z odwołaniami do kolumn bezpośrednio do ramki danych pandy.

Krótkie i słodkie:

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


Szczegóły kodu i podsumowanie regresji:

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

Wynik:

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

Jak bezpośrednio uzyskać R-kwadrat, współczynniki i wartość 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
Vestland
źródło