web-dev-qa-db-fra.com

Option de fenêtre roulante obsolète dans OLS, des pandas aux modèles statistiques

comme le titre l'indique, où est passée l'option de fonction de roulement dans la commande ols de Pandas dans les modèles de statistiques? Je n'arrive pas à le trouver . Pandas me dit que Doom est en chantier:

FutureWarning: 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://statsmodels.sourceforge.net/stable/regression.html
  model = pd.ols(y=series_1, x=mmmm, window=50)

en fait, si vous faites quelque chose comme:

import statsmodels.api as sm

model = sm.OLS(series_1, mmmm, window=50).fit()

print(model.summary())

vous obtenez des résultats (la fenêtre ne gêne pas l'exécution du code) mais vous obtenez uniquement les paramètres de la régression exécutée sur l'ensemble de la période, et non la série de paramètres de chacune des périodes glissantes sur lesquelles elle devrait être utilisée.

12
Asher11

J'ai créé un module ols conçu pour imiter les obsolètes MovingOLS des pandas; c'est ici .

Il comporte trois classes principales:

  • OLS: régression des moindres carrés ordinaires statique (à fenêtre unique). Les sorties sont des tableaux NumPy
  • RollingOLS: régression par les moindres carrés ordinaires défilant sur plusieurs fenêtres. Les résultats sont des tableaux NumPy de dimension supérieure.
  • PandasRollingOLS: encapsule les résultats de RollingOLS dans les pandas Series et DataFrames. Conçu pour imiter le look du module de pandas obsolètes.

Notez que le module fait partie d'un package (que je suis en train de télécharger sur PyPi) et qu'il nécessite une importation inter-packages.

Les deux premières classes ci-dessus sont entièrement implémentées dans NumPy et utilisent principalement l'algèbre matricielle. RollingOLS profite également beaucoup de la radiodiffusion. Les attributs imitent en grande partie les statistiques de modèle OLS RegressionResultsWrapper.

Un exemple:

# Pull some data from fred.stlouisfed.org
from pandas_datareader.data import DataReader

syms = {'TWEXBMTH' : 'usd', 
        'T10Y2YM' : 'term_spread', 
        'PCOPPUSDM' : 'copper'
       }
data = (DataReader(syms.keys(), 'fred', start='2000-01-01')
        .pct_change()
        .dropna())
data = data.rename(columns=syms)
print(data.head())
                # usd  term_spread   copper
# DATE                                     
# 2000-02-01  0.01260     -1.40909 -0.01997
# 2000-03-01 -0.00012      2.00000 -0.03720
# 2000-04-01  0.00564      0.51852 -0.03328
# 2000-05-01  0.02204     -0.09756  0.06135
# 2000-06-01 -0.01012      0.02703 -0.01850

# Rolling regressions

from pyfinance.ols import PandasRollingOLS

y = data.usd
x = data.drop('usd', axis=1)

window = 12  # months
model = PandasRollingOLS(y=y, x=x, window=window)

print(model.beta.head())  # Coefficients excluding the intercept
            # term_spread   copper
# DATE                            
# 2001-01-01      0.00010  0.05568
# 2001-02-01      0.00047  0.06271
# 2001-03-01      0.00147  0.03576
# 2001-04-01      0.00161  0.02956
# 2001-05-01      0.00158 -0.04497

print(model.fstat.head())
# DATE
# 2001-01-01    0.28121
# 2001-02-01    0.42602
# 2001-03-01    0.38802
# 2001-04-01    0.39230
# 2001-05-01    0.41706
# Freq: MS, Name: fstat, dtype: float64

print(model.rsq.head())  # R-squared
# DATE
# 2001-01-01    0.05882
# 2001-02-01    0.08648
# 2001-03-01    0.07938
# 2001-04-01    0.08019
# 2001-05-01    0.08482
# Freq: MS, Name: rsq, dtype: float64
8
Brad Solomon

Bêta roulante avec sklearn 

import pandas as pd
from sklearn import linear_model

def rolling_beta(X, y, idx, window=255):

    assert len(X)==len(y)

    out_dates = []
    out_beta = []

    model_ols = linear_model.LinearRegression()

    for iStart in range(0, len(X)-window):        
        iEnd = iStart+window

        model_ols.fit(X[iStart:iEnd], y[iStart:iEnd])

        #store output
        out_dates.append(idx[iEnd])
        out_beta.append(model_ols.coef_[0][0])

    return pd.DataFrame({'beta':out_beta}, index=out_dates)


df_beta = rolling_beta(df_rtn_stocks['NDX'].values.reshape(-1, 1), df_rtn_stocks['CRM'].values.reshape(-1, 1), df_rtn_stocks.index.values, 255)
6
citynorman

Ajouter pour compléter une solution plus rapide numpy- qui limite les calculs aux coefficients de régression et à l'estimation finale 

Fonction de régression glissante Numpy

import numpy as np

def rolling_regression(y, x, window=60):
    """ 
    y and x must be pandas.Series
    """
# === Clean-up ============================================================
    x = x.dropna()
    y = y.dropna()
# === Trim acc to shortest ================================================
    if x.index.size > y.index.size:
        x = x[y.index]
    else:
        y = y[x.index]
# === Verify enough space =================================================
    if x.index.size < window:
        return None
    else:
    # === Add a constant if needed ========================================
        X = x.to_frame()
        X['c'] = 1
    # === Loop... this can be improved ====================================
        estimate_data = []
        for i in range(window, x.index.size+1):
            X_slice = X.values[i-window:i,:] # always index in np as opposed to pandas, much faster
            y_slice = y.values[i-window:i]
            coeff = np.dot(np.dot(np.linalg.inv(np.dot(X_slice.T, X_slice)), X_slice.T), y_slice)
            estimate_data.append(coeff[0] * x.values[window-1] + coeff[1])
    # === Assemble ========================================================
        estimate = pandas.Series(data=estimate_data, index=x.index[window-1:]) 
        return estimate             

Remarques

Dans certains cas spécifiques, qui ne nécessitent que l'estimation finale de la régression, x.rolling(window=60).apply(my_ols) semble être un peu lent 

Pour rappel, les coefficients d'une régression peuvent être calculés sous forme de produit matriciel, comme vous pouvez le lire sur la page page des moindres carrés de wikipedia . Cette approche via la multiplication matricielle de numpy peut accélérer le processus quelque peu par rapport à l’utilisation des ols dans statsmodels. Ce produit est exprimé dans la ligne commençant par coeff = ...

0
Pythonic