[英]Cumulative OLS with Python Pandas
我正在使用Pandas 0.8.1,目前我無法更改版本。 如果新版本有助於解決以下問題,請在評論中注明,而不是回答。 此外,這是一個研究復制項目,所以即使在僅附加一個新數據點后重新運行回歸可能是愚蠢的(如果數據集很大),我仍然必須這樣做。 謝謝!
在熊貓,還有一個rolling
的選項window_type
參數pandas.ols
但似乎暗示,這需要一個窗口大小或使用整個數據樣本為默認的一些選擇。 我希望以累積的方式使用所有數據。
我正在嘗試對按日期排序的pandas.DataFrame
運行回歸。 對於每個索引i
,我想使用從索引i
的最小日期到日期的可用數據運行回歸。 因此,窗口在每次迭代時有效地增加一個,所有數據從最早的觀察中累積使用,並且沒有數據從窗口中丟失。
我已經編寫了一個函數(下面),可以使用apply
來執行此操作,但它的速度慢得令人無法接受。 相反,有沒有辦法使用pandas.ols
直接執行這種累積回歸?
以下是有關我的數據的更多細節。 我有一個pandas.DataFrame
其中包含一列標識符,一列日期,一列左側值和一列右側值。 我想使用groupby
基於標識符進行分組,然后對包含左側和右側變量的每個時間段執行累積回歸。
這是我能夠使用的功能, apply
標識符分組對象:
def cumulative_ols(
data_frame,
lhs_column,
rhs_column,
date_column,
min_obs=60
):
beta_dict = {}
for dt in data_frame[date_column].unique():
cur_df = data_frame[data_frame[date_column] <= dt]
obs_count = cur_df[lhs_column].notnull().sum()
if min_obs <= obs_count:
beta = pandas.ols(
y=cur_df[lhs_column],
x=cur_df[rhs_column],
).beta.ix['x']
###
else:
beta = np.NaN
###
beta_dict[dt] = beta
###
beta_df = pandas.DataFrame(pandas.Series(beta_dict, name="FactorBeta"))
beta_df.index.name = date_column
return beta_df
根據評論中的建議,我創建了自己的函數,可以與apply
一起使用,並且依賴於cumsum
來積累所有單獨需要的術語,用於從OLS單變量回歸中表達系數。
def cumulative_ols(
data_frame,
lhs_column,
rhs_column,
date_column,
min_obs=60,
):
"""
Function to perform a cumulative OLS on a Pandas data frame. It is
meant to be used with `apply` after grouping the data frame by categories
and sorting by date, so that the regression below applies to the time
series of a single category's data and the use of `cumsum` will work
appropriately given sorted dates. It is also assumed that the date
conventions of the left-hand-side and right-hand-side variables have been
arranged by the user to match up with any lagging conventions needed.
This OLS is implicitly univariate and relies on the simplification to the
formula:
Cov(x,y) ~ (1/n)*sum(x*y) - (1/n)*sum(x)*(1/n)*sum(y)
Var(x) ~ (1/n)*sum(x^2) - ((1/n)*sum(x))^2
beta ~ Cov(x,y) / Var(x)
and the code makes a further simplification be cancelling one factor
of (1/n).
Notes: one easy improvement is to change the date column to a generic sort
column since there's no special reason the regressions need to be time-
series specific.
"""
data_frame["xy"] = (data_frame[lhs_column] * data_frame[rhs_column]).fillna(0.0)
data_frame["x2"] = (data_frame[rhs_column]**2).fillna(0.0)
data_frame["yobs"] = data_frame[lhs_column].notnull().map(int)
data_frame["xobs"] = data_frame[rhs_column].notnull().map(int)
data_frame["cum_yobs"] = data_frame["yobs"].cumsum()
data_frame["cum_xobs"] = data_frame["xobs"].cumsum()
data_frame["cumsum_xy"] = data_frame["xy"].cumsum()
data_frame["cumsum_x2"] = data_frame["x2"].cumsum()
data_frame["cumsum_x"] = data_frame[rhs_column].fillna(0.0).cumsum()
data_frame["cumsum_y"] = data_frame[lhs_column].fillna(0.0).cumsum()
data_frame["cum_cov"] = data_frame["cumsum_xy"] - (1.0/data_frame["cum_yobs"])*data_frame["cumsum_x"]*data_frame["cumsum_y"]
data_frame["cum_x_var"] = data_frame["cumsum_x2"] - (1.0/data_frame["cum_xobs"])*(data_frame["cumsum_x"])**2
data_frame["FactorBeta"] = data_frame["cum_cov"]/data_frame["cum_x_var"]
data_frame["FactorBeta"][data_frame["cum_yobs"] < min_obs] = np.NaN
return data_frame[[date_column, "FactorBeta"]].set_index(date_column)
### End cumulative_ols
我已經在許多測試用例中驗證了這與我以前的函數的輸出和NumPy的linalg.lstsq
函數的輸出相匹配。 我沒有對時間進行完整的基准測試,但有趣的是,在我一直在努力的情況下它快了大約50倍。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.