我有一个由许多堆叠时间序列组成的 DataFrame。索引是 (poolId, month),其中两个都是整数,“月”是自 2000 年以来的月数。计算多个变量的一个月滞后版本的最佳方法是什么?
现在,我做类似的事情:
cols_to_shift = ["bal", ...5 more columns...]
df_shift = df[cols_to_shift].groupby(level=0).transform(lambda x: x.shift(-1))
对于我的数据,我运行了整整 60 秒。(我有 48k 不同的池和总共 718k 行。)
我正在从 R 代码和等效的 data.table 调用中转换它:
dt.shift <- dt[, list(bal=myshift(bal), ...), by=list(poolId)]
只需 9 秒即可运行。(这里的“myshift”类似于“function(x) c(x[-1], NA)”。)
有没有办法让熊猫版本在速度方面恢复正常?我在 0.8.1 上对此进行了测试。
编辑:这是一个生成足够接近的数据集的示例,因此您可以了解我的意思:
ids = np.arange(48000)
lens = np.maximum(np.round(15+9.5*np.random.randn(48000)), 1.0).astype(int)
id_vec = np.repeat(ids, lens)
lens_shift = np.concatenate(([0], lens[:-1]))
mon_vec = np.arange(lens.sum()) - np.repeat(np.cumsum(lens_shift), lens)
n = len(mon_vec)
df = pd.DataFrame.from_items([('pool', id_vec), ('month', mon_vec)] + [(c, np.random.rand(n)) for c in 'abcde'])
df = df.set_index(['pool', 'month'])
%time df_shift = df.groupby(level=0).transform(lambda x: x.shift(-1))
我尝试时花了 64 秒。该数据的每个系列都从第 0 个月开始;真的,它们都应该在 np.max(lens) 月结束,开始日期参差不齐,但已经足够好了。
编辑 2:这是一些比较 R 代码。这需要 0.8 秒。80 的系数,不好。
library(data.table)
ids <- 1:48000
lens <- as.integer(pmax(1, round(rnorm(ids, mean=15, sd=9.5))))
id.vec <- rep(ids, times=lens)
lens.shift <- c(0, lens[-length(lens)])
mon.vec <- (1:sum(lens)) - rep(cumsum(lens.shift), times=lens)
n <- length(id.vec)
dt <- data.table(pool=id.vec, month=mon.vec, a=rnorm(n), b=rnorm(n), c=rnorm(n), d=rnorm(n), e=rnorm(n))
setkey(dt, pool, month)
myshift <- function(x) c(x[-1], NA)
system.time(dt.shift <- dt[, list(month=month, a=myshift(a), b=myshift(b), c=myshift(c), d=myshift(d), e=myshift(e)), by=pool])