在大型DataFrame上进行滚动线性回归

时间:2018-02-15 21:29:17

标签: python dataframe statistics linear-regression statsmodels

我有两个巨大的数据框df_ydf_x
df_y['date','ids','Y']。基本上每个'ids'都包含所有'date'的数据 df_x['date','X1','X2','X3','X4','X5','X6']
df_x包含date中的所有df_y。但是,某些ids可能会有较短的时间段,即从晚date开始或结束  在date早期 我想为Id ~ X1 + X2 + X3 + X4 + X5 + X6 + intercept中的每个'ids'运行滚动线性回归(OLS)df_y,回顾期为200天。

示例数据框:

import string, random, pandas as pd, numpy as np
ids = [''.join(random.choice(string.ascii_uppercase) for _ in range(3)) for _ in range(200)]
dates = pd.date_range('2000-01-01', '2017-07-02')
df_dates = pd.DataFrame({'date':dates, 'joinC':len(dates)*[2]})
df_ids = pd.DataFrame({'ids':ids, 'joinC':len(ids)*[2]})
df_values = pd.DataFrame({'Y':np.random.normal(size = 
len(dates)*len(ids))})
df_y = df_dates.merge(df_ids, on='joinC', how="outer")
df_y = df_y[['date', 'ids']].merge(df_values, left_index=True, 
right_index=True, how="inner")
df_y = df_y.sort_values(['date', 'ids'], ascending=[True, True])
df_x = pd.DataFrame({'date':dates, 'X1':np.random.normal(size = len(dates)), 'X2':np.random.normal(size = len(dates)), 'X3':np.random.normal(size = len(dates)), 'X4':np.random.normal(size = len(dates)), 'X5':np.random.normal(size = len(dates)), 'X6':np.random.normal(size = len(dates))})

我的尝试:

import statsmodels.api as sm
dates = list(df_y['date'].unique())
ids = list(df_y['ids'].unique())
for i in range(200, len(dates) +1):
  for id in ids:
    s_date = dates[i - 200]
    e_date = dates[i - 1]
    Y = df_y[(df_y['date'] >= s_date) & (df_y['date'] <= e_date) & (df_y['ids'] == id)]['Y']
    Y = Y.reset_index()['Y']
    X = df_x[(df_x['date'] >= s_date) & (df_x['date'] <= e_date)]
    X = X.reset_index()[['X1','X2','X3','X4','X5','X6']]
    X = sm.add_constant(X)
    if len(X) <> len(Y):
      continue
    regr = sm.OLS(Y, X).fit()  #Hangs here after 2 years.
    X_pr = X.tail(1)
    Y_hat = regr.predict(X_pr)
    Y.loc[(df_y['date'] == e_date) & (df_y['ids'] == id), 'Y_hat'] = Y_hat.tolist()[0]

上面的尝试似乎工作正常,直到它在运行大约之后挂起(最有可能在装配步骤)。 2年。我倾向于使用statsmodels,因为它支持正规化(规划未来的工作)。但是,如果使用其他库使其更快或更优雅,那么我也很好。有人可以帮助定义一个不会中途悬挂的最快解决方案。非常感谢。

1 个答案:

答案 0 :(得分:0)

我能够使用Pandas MovingOLS获得此解决方法

import pandas as pd
dates = list(df_y['date'].unique())
ids = list(df_y['ids'].unique())
Y_hats = []
for id in ids:
    Y = df_y[(df_y['ids'] == id)][['date', 'ids', 'Y']]
    Y = Y.merge(df_x, how='left', on=['date'])
    X_cols = list(df_x.columns).remove['date']
    model = pd.stats.ols.MovingOLS(y=Y['Y'], x=Y[X_cols], window_type='rolling', window=250, intercept=True)
    Y['intercept'] = 1
    betas = model.beta
    betas = betas.multiply(Y[betas.columns], axis='index')
    betas = betas.sum(axis=1)
    betas = betas[betas > 0]
    betas = betas.to_frame()
    betas.columns = [['Y_hat']]
    betas = betas.merge(Y[['date', 'ids']], how='left', left_index=True, right_index=True)
    Y_hats.append(betas)
Y_hats = pd.concat(Y_hats)
Y = Y.merge(Y_hats[['date', 'ids', 'Y_hat'], how='left', on=['date', 'ids']]

有一种直接的方法可以使用Y['Y_hat'] = model.y_predict,如果我们想让Y ~ X符合(y_1, y_2, ... y_n)(x_1, x_2, ... x_n),但只想预测使用Y_(n+1) X_(n+1)