使用带有data.table的滚动功能

问题描述 投票:0回答:2

我在使用roll专门应用data.table包中的函数时遇到了问题。我正在尝试为每个组DT$obs计算DT$group列的滚动指标。我可以使用zoo包计算滚动指标,但我想在roll包函数中使用一些额外的参数。

演示错误如下。

require(data.table)
require(zoo)
require(roll)


# Fabricated Data:
DT <- data.table(group = rep(c("A", "B"), each = 20), obs = runif(40, min = 0, max = 100))


# Calculate a rolling sum (this is working properly)
DT[, RollingSum := lapply(.SD, function(x) zoo::rollsumr(x, k = 5, fill = NA)), by = "group", .SDcols = "obs"]


# Attempt to calculate a rolling z-score (this throws me an error)
DT[, RollingZScore := lapply(.SD, function(x) roll::roll_scale(as.matrix(x), width = 10, min_obs = 5)), by = "group", .SDcols = "obs"]

enter image description here

我无法弄清楚zoo函数和roll函数有什么不同。它们各自返回数字向量。任何指导赞赏。

r data.table vectorization
2个回答
2
投票

正如@Frank所描述的那样,问题是roll_scale(因此lapply输出的每个元素)的结果是一个矩阵。您可以使用sapply而不是lapply,或者将as.vector放在函数定义中。

DT[, RollingZScore := sapply(.SD, 
                             function(x) roll::roll_scale(as.matrix(x), width = 10, min_obs = 5)), 
   by = "group", .SDcols = "obs"]

要么

DT[, RollingZScore := lapply(.SD, 
                              function(x) as.vector(roll::roll_scale(as.matrix(x), width = 10, min_obs = 5))), 
    by = "group", .SDcols = "obs"]

1
投票

这可以通过rollapplyr完成,只需定义一个函数,如果输入的元素少于5个,则返回NA

Scale <- function(x) if (length(x) < 5) NA else tail(scale(x), 1)
DT[, rollingScore := rollapplyr(obs, 10, Scale, partial = TRUE), by = "group"]
© www.soinside.com 2019 - 2024. All rights reserved.