2017-06-06 25 views
24

私は、非推奨のstats/olsモジュール内のパンダのMovingOLSクラス(ソースhere)からうまく使い果たしました。残念ながら、それはパンダ0.20で完全に撃たれました。パンダローリング回帰:ループの代替

ローリングOLS回帰を効率的に実行する方法についての質問は、複数回(例えばhere)尋ねられましたが、私の見解では少し広範に言い表せました。

ここに私の質問は以下のとおりです。

  1. がどのように私は最高のMovingOLSパンダの基本的な枠組みを模倣することができますか?このクラスの最も魅力的な機能は、複数のメソッド/属性を別々の時系列として表示する機能です。係数、r-squared、t-statisticsなどを使用して、回帰を再実行する必要はありません。たとえば、model = pd.MovingOLS(y, x)のようなものを作成し、.t_stat.rmse.std_errなどを呼び出すことができます。下の例では、逆に、私は別々に各統計量を強制的に計算する方法を見ていません。スライディング/ローリング "ブロック"(ストライド)の作成と回帰の実行/それぞれのモデルパラメータを得るための線形代数の使用を伴わない方法はありますか?

  2. より広く、作ることパンダにフードの下で何が起こっているかrolling.applyより複雑な機能を取る*あなたが.rollingオブジェクトを作成すると、素人の観点からできない、内部で何が起こっているのか? - それは基本的に異なります私は以下のように各ウィンドウをループし、高次の配列を作成しますか? .applyに渡さ

*つまり、func

がndarray入力から単一の値を生成しなければならない*引数と** kwargsから が関数に

を渡され、ここどこです私は現在、金利スプレッドと銅の価格に関する貿易加重ドルのパーセンテージの変化を回帰するいくつかのサンプルデータを持っています。 (これは意味がありません;これらを無作為に選んだだけです)クラスベースの実装から取り除き、より簡単なスクリプトに切り離そうとしました。

from datetime import date 
from pandas_datareader.data import DataReader 
import statsmodels.formula.api as smf 

syms = {'TWEXBMTH' : 'usd', 
     'T10Y2YM' : 'term_spread', 
     'PCOPPUSDM' : 'copper' 
     } 

start = date(2000, 1, 1) 
data = (DataReader(syms.keys(), 'fred', start) 
     .pct_change() 
     .dropna()) 
data = data.rename(columns = syms) 
data = data.assign(intercept = 1.) # required by statsmodels OLS 

def sliding_windows(x, window): 
    """Create rolling/sliding windows of length ~window~. 

    Given an array of shape (y, z), it will return "blocks" of shape 
    (x - window + 1, window, z).""" 

    return np.array([x[i:i + window] for i 
        in range(0, x.shape[0] - window + 1)]) 

data.head(3) 
Out[33]: 
       usd term_spread copper intercept 
DATE             
2000-02-01 0.012573 -1.409091 -0.019972  1.0 
2000-03-01 -0.000079  2.000000 -0.037202  1.0 
2000-04-01 0.005642  0.518519 -0.033275  1.0 

window = 36 
wins = sliding_windows(data.values, window=window) 
y, x = wins[:, :, 0], wins[:, :, 1:] 

coefs = [] 

for endog, exog in zip(y, x): 
    model = smf.OLS(endog, exog).fit() 
     # The full set of model attributes gets lost with each loop 
    coefs.append(model.params) 

df = pd.DataFrame(coefs, columns=data.iloc[:, 1:].columns, 
        index=data.index[window - 1:]) 

df.head(3) # rolling 36m coefficients 
Out[70]: 
      term_spread copper intercept 
DATE           
2003-01-01 -0.000122 -0.018426 0.001937 
2003-02-01  0.000391 -0.015740 0.001597 
2003-03-01  0.000655 -0.016811 0.001546 
+2

。私はパンダをよく知っていないので私の答えは無回答ですhttps://github.com/statsmodels/statsmodels/issues/2302#issuecomment-306389959 – user333700

+0

ここに私の考えがあります。私はハードコアですPandas and R user:回帰関係の場合、PythonではなくRを使います。与えられた、あなたは約を行うことができます。同じことですが、PythonはRのパッケージの幅と一致しません。さらに、 'broom'のようなパッケージを用意しています。これらの回帰統計を非常に簡単に把握し、それらをデータフレームやラテックステーブルに入れることができます。 –

+0

MovingOLSは機能しませんか、それとも単に削除されましたか?あなたはMovingOLSのコードを手に入れて、あなたの小さなライブラリを効果的に作ることができますか? – BrenBarn

答えて

4

私はパンダを模倣するように設計されolsモジュールはMovingOLSを非推奨に作成。 hereです。

これは3つのコアクラスがあります

  • OLS:静的(シングルウィンドウ)通常最小二乗回帰。出力はNumPy配列
  • RollingOLS:ローリング(マルチウィンドウ)通常最小二乗回帰です。出力は、より高次元のNumPy配列です。
  • PandasRollingOLS:パンダの&データフレームにはRollingOLSの結果がラップされています。非推奨のpandasモジュールの外観を模倣するように設計されています。

このモジュールはpackage(現在はPyPI上にあります)の一部であり、1つのパッケージ間インポートが必要であることに注意してください。

最初の2つのクラスが上記numpyの中に完全に実装され、主に行列代数を使用します。 RollingOLSも広範に放送を利用しています。属性は主にstatsmodelsのOLS RegressionResultsWrapperに似ています。

例:私はあなたのループを使用し、1回のパスで必要なすべての属性と結果を格納します基本的な回避策として

# 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 OLS, RollingOLS, 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 
+1

このアプローチの主な問題は、すべてのOLSインスタンスを周りに保つには大量のメモリが必要だということです。 – user333700

+0

@ user333700私はあなたが一見することに興味があるなら、記憶にもっと親切にすべきいくつかの大きな変更を加えました。 –