使用R

时间:2019-08-25 13:57:33

标签: r data.table grouping vertical-scrolling rolling-computation

我正在尝试为滚动窗口(例如12磅)中的字符列(但按组)创建一个更改数量的指示器。如果不进行分组,则rollapply和data.table的uniqueN可以使用 data.table

library(data.table)
library(zoo)
df <- data.table(id = c(rep(1:5, each = 53), 5), 
             time = c(rep(1:53, times = 5), 54), 
             geo = c("E","E","E","B","B","B","B","B","B","B","A","A","A","A","A","A","A","C","C","C","C","C","C","C","G","G","G","G","G","G","G","G","G","C","C","C","C","C","C","C","C","C","C","C","C","C","C","C","C","C","C","C","C","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","D","D","D","D","D","D","G","G","G","G","G","E","E","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","I","I","I","I","I","B","B","B","B","B","B","B","B","B","D","D","D","D","D","D","D","D","D","D","D","D","E","E","E","E","E","E","E","E","E","E","E","E","E","E","E","I","I","I","I","I","I","I","I","H","C","C","C","C","C","C","C","C","C","G","G","G","G","G","G","G","G","G","G","G","G","G","G","G","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","B","B","B","B","B","B","B","B","B","B","B","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","I","I","I","I","I","I","E","E","E","E","E","E","E","E","E","E","F","F","A","A","A","A","A"))

# works
df[, change := rollapply(geo, width = 12, FUN = uniqueN, na.pad = TRUE, align = "right")]

但是当我按 id 对它们进行分组时,它不起作用

# does not work
df[, change := rollapply(geo, width = 12, FUN = uniqueN, na.pad = TRUE, align = "right"), by = id]

是否有一种方法可以滚动唯一计数,最好使用 data.table

2 个答案:

答案 0 :(得分:1)

通过将rollapply函数包装在as.numeric中解决了该问题,因为变量 change 被创建为逻辑变量,无法处理0和1(以及NA)以外的数字)。

如果我们将此问题保留为开放状态,这可能对其他人有帮助。

# works
df[, change := as.numeric(rollapplyr(geo, width = 12, FUN = uniqueN, fill = NA)), by = id]

答案 1 :(得分:1)

rollapply即将推出新的快速版本data.table功能。它称为frollapply。速度不是真的那么快,但是仍然应该加快速度。 速度并不是真的那么快,因为在滚动窗口的每次迭代中都必须回退到R的C eval函数。

它接受数字或逻辑输入,因此要处理您的数据,我们需要创建一个临时ngeo列。

library(data.table)
library(zoo)
df = data.table(
  id = c(rep(1:5, each = 53), 5), time = c(rep(1:53, times = 5), 54), 
  geo = c("E","E","E","B","B","B","B","B","B","B","A","A","A","A","A","A","A","C","C","C","C","C","C","C","G","G","G","G","G","G","G","G","G","C","C","C","C","C","C","C","C","C","C","C","C","C","C","C","C","C","C","C","C","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","D","D","D","D","D","D","G","G","G","G","G","E","E","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","I","I","I","I","I","B","B","B","B","B","B","B","B","B","D","D","D","D","D","D","D","D","D","D","D","D","E","E","E","E","E","E","E","E","E","E","E","E","E","E","E","I","I","I","I","I","I","I","I","H","C","C","C","C","C","C","C","C","C","G","G","G","G","G","G","G","G","G","G","G","G","G","G","G","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","B","B","B","B","B","B","B","B","B","B","B","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","I","I","I","I","I","I","E","E","E","E","E","E","E","E","E","E","F","F","A","A","A","A","A")
)
dt = copy(df)

# zoo rollapply
df[, change := as.numeric(rollapplyr(geo, width=12, FUN=uniqueN, fill=NA)), by=id]

# data.table frollapply
dt[, ngeo := unclass(as.factor(geo))]
dt[, change := frollapply(ngeo, 12L, FUN=uniqueN), by=id]
dt[, ngeo := NULL]

all.equal(dt, df)
#[1] TRUE

它尚未合并到data.table的主分支中,要尝试,您必须

devtools::install_github("Rdatatable/data.table@frollapply")