如何解决R data.table 中具有阈值窗口的累积和
我想计算数据集中 n 行的滚动总和,其中窗口大小“n”取决于总和本身。例如,我想在滚动时间总和超过 5 分钟时滑动窗口。基本上,我想计算这个人在过去 5 分钟内走过的距离,但时间步长不是等距的。为了清楚起见,这里有一个虚拟的 data.table(最后两列是必需的):
我正在 R 中寻找 data.table 解决方案
输入数据表:
ID | 距离 | 时间 |
---|---|---|
1 | 2 | 2 |
1 | 4 | 1 |
1 | 2 | 1 |
1 | 2 | 2 |
1 | 3 | 3 |
1 | 6 | 3 |
1 | 1 | 1 |
期望的输出:
ID | 距离 | 时间 | 5.min.rolling.distance | 5.min.rolling.time |
---|---|---|---|---|
1 | 2 | 2 | 不适用 | 不适用 |
1 | 4 | 1 | 不适用 | 不适用 |
1 | 2 | 1 | 不适用 | 不适用 |
1 | 2 | 2 | 10 | 6 |
1 | 3 | 3 | 5 | 5 |
1 | 6 | 3 | 9 | 6 |
1 | 1 | 1 | 10 | 7 |
解决方法
这是一个适用于 double
时间单位的解决方案,以及适用于 integer
时间单位的更简单的解决方案。我在 10,000 条记录上测试了 double
解决方案,并在我 2015 年的笔记本电脑上立即执行。我无法保证 40 GB 数据的性能。
如果您想概括此代码,我会查看 RcppRoll package 并学习如何在 R 中实现 C++ 代码。
具有 double
个时间单位的解决方案
我把它分解成两个问题。首先,通过回顾直到我们到达至少 5 分钟(或用完数据)来计算窗口大小。其次,取从当前观察到回溯单元的距离和时间之和。
R 中的错误循环代码通常会尝试“增长”向量,预先分配向量长度然后更改其中的元素可以极大地提高效率。
input <- data.frame(
dist = c(2,4,2,3,6,1),time = c(2,1,1)
)
var_window_cumsum <- function(input,MIN_TIME) {
if(is.null(input$time) | is.null(input$dist)) {
stop("input must have variables time and dist that record the row's duration and distance traveled.")
}
n <- nrow(input)
# First,figure out how far we need to look back to,this vector will store
# the position of the first record that gets our target record up to 5 min or
# more. If we cant look back to 5 min,we leave it as NA.
time_indx = rep(NA_integer_,length = n) # always preallocate your vector!
for(time in (1:n)) {
prior = time # start at self in case observation is already >= MIN_TIME
while(sum(input$time[time:prior]) < MIN_TIME & prior > 1) {
prior = prior - 1
}
# if we cant look back to our minimum time,leave the indx as NA
if (sum(input$time[time:prior]) >= MIN_TIME) {
time_indx[time] = prior
}
}
# Now that we know how far to look back,its easy to find out the total distance
# and total time.
dist5 = rep(NA_integer_,n)
time5 = rep(NA_integer_,n)
for (i in 1:n) {
dist5[i] <- ifelse(!is.na(time_indx[i]),sum(input$dist[i:time_indx[i]]),NA)
time5[i] <- ifelse(!is.na(time_indx[i]),sum(input$time[i:time_indx[i]]),NA)
}
cbind(input,window_dist = dist5,window_time = time5,window_start = time_indx)
}
# output looks good
# Warning: example data does not include exhaustive cases
# I have not setup thorough testing
var_window_cumsum(input,5)
# Test on a larger dataset,10k records
set.seed(1234)
n <- 10000
med_input <- data.frame(
dist = sample(1:5,n,replace = TRUE),time = sample(1:60,replace = TRUE) / 10
)
# you should inspect this to make sure there are no errors
med_output <- var_window_cumsum(med_input,5)
具有 integer
个时间单位的解决方案
如果您的时间单位是整数并且您的数据不是太大,则它可能适用于 complete
您的数据集。这是一个小技巧,但在这里我创建了一个从开始时间到最大时间的连续 timeid
变量,并为每个整数时间单位创建一行。从那里很容易计算最后五个时间单位的滚动累积总和。最后,我们删除了我们添加的所有假行(您要确保这样做,因为它们将具有无效的累积总和数据。另外,重要的是要注意我使用 roll_sumr
而不是 {{1} }; roll_sum
在前 4 个单位的输出向量左侧包含 4 个填充 NA。
roll_sumr
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。