在大型 DataFrame 上滚动线性回归
Rolling linear regression on large DataFrames
我有两个巨大的数据框 df_y
和 df_x
。
df_y
有列 ['date','ids','Y']
。基本上每个 'ids'
都有所有 'date'
.
的数据
df_x
有列 ['date','X1','X2','X3','X4','X5','X6']
。
df_x
拥有 df_y
中的所有 date
。然而,有些 ids
可能有较短的周期,即从较晚的 date
开始或结束
早 date
.
我想 运行 对 df_y
中的每个 'ids'
进行滚动线性回归 (OLS) Id ~ X1 + X2 + X3 + X4 + X5 + X6 + intercept
,回溯 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]
我上面的尝试 似乎工作正常,直到它在 运行ning 后挂起(很可能在安装步骤)大约。 2年。我倾向于使用 statsmodels
因为它支持正则化(为未来的工作做规划)。但是,如果使用其他库使它更快或更优雅,那么我也很好。有人可以帮助定义不会中途挂起的最快解决方案。非常感谢。
我能够使用 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_1, y_2, ... y_n)
和 (x_1, x_2, ... x_n)
上拟合 Y ~ X
但只想预测 Y_(n+1)
使用 X_(n+1)
.
我有两个巨大的数据框 df_y
和 df_x
。
df_y
有列 ['date','ids','Y']
。基本上每个 'ids'
都有所有 'date'
.
的数据
df_x
有列 ['date','X1','X2','X3','X4','X5','X6']
。
df_x
拥有 df_y
中的所有 date
。然而,有些 ids
可能有较短的周期,即从较晚的 date
开始或结束
早 date
.
我想 运行 对 df_y
中的每个 'ids'
进行滚动线性回归 (OLS) Id ~ X1 + X2 + X3 + X4 + X5 + X6 + intercept
,回溯 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]
我上面的尝试 似乎工作正常,直到它在 运行ning 后挂起(很可能在安装步骤)大约。 2年。我倾向于使用 statsmodels
因为它支持正则化(为未来的工作做规划)。但是,如果使用其他库使它更快或更优雅,那么我也很好。有人可以帮助定义不会中途挂起的最快解决方案。非常感谢。
我能够使用 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_1, y_2, ... y_n)
和 (x_1, x_2, ... x_n)
上拟合 Y ~ X
但只想预测 Y_(n+1)
使用 X_(n+1)
.