R 中计算滑动时间每个 ID 行数的有效方法 window?
Efficient way in R to count lines per ID on sliding time window?
任何包中是否有任何函数可以计算一行中的 ID 在过去 x 小时内出现了多少次。我称之为 'velocity'.
我要计算的目标列用'VEL_7H'表示。也就是说,这个ID在过去7小时内出现了多少次?
ID TIME VEL_7H
1144727 2016-04-01 09:56:12 0
1144727 2016-04-01 15:16:03 1
1144727 2016-04-01 15:26:14 2
1144727 2016-04-02 09:48:48 0
1799567 2016-04-14 14:41:06 0
1799567 2016-04-14 17:51:06 1
2067650 2016-04-17 12:34:52 0
是否有使用时间和 ID 向量以及指定范围的函数给出 VEL_7H 列?
为了最大化性能,我认为Rcpp是合适的:
library(Rcpp);
df <- data.frame(ID=c(1144727L,1144727L,1144727L,1144727L,1799567L,1799567L,2067650L),TIME=as.POSIXct(c('2016-04-01 09:56:12','2016-04-01 15:16:03','2016-04-01 15:26:14','2016-04-02 09:48:48','2016-04-14 14:41:06','2016-04-14 17:51:06','2016-04-17 12:34:52')));
cppFunction('
IntegerVector countTrailingIDs(IntegerVector ids, DoubleVector times, double window ) {
IntegerVector res(ids.size());
for (int i = 0; i < ids.size(); ++i) {
int id = ids[i];
double trailTime = times[i]-window;
for (int j = i-1; j >= 0 && ids[j] == id && times[j] >= trailTime; --j)
++res[i];
}
return res;
}
');
df$VEL_7H <- countTrailingIDs(df$ID,df$TIME,60*60*7);
df;
## ID TIME VEL_7H
## 1 1144727 2016-04-01 09:56:12 0
## 2 1144727 2016-04-01 15:16:03 1
## 3 1144727 2016-04-01 15:26:14 2
## 4 1144727 2016-04-02 09:48:48 0
## 5 1799567 2016-04-14 14:41:06 0
## 6 1799567 2016-04-14 17:51:06 1
## 7 2067650 2016-04-17 12:34:52 0
注意函数需要ids
和times
先id后time排序
我们可以在 base R 中使用经典的拆分-应用-组合方法,首先按 ID 拆分数据框,将过去 7 小时内的条目数量相加,然后创建一个包含以下值的新列:
sdf <- split(df, df$ID)
last7 <- function(df) sapply(1:nrow(df), function(i) sum(df[i, "TIME"] - df[1:i, "TIME"] <= 60*60*7) - 1L)
df$VEL_7H <- unlist(sapply(sdf, last7))
df
# ID TIME VEL_7H
# 1 1144727 2016-04-01 09:56:12 0
# 2 1144727 2016-04-01 15:16:03 1
# 3 1144727 2016-04-01 15:26:14 2
# 4 1144727 2016-04-02 09:48:48 0
# 5 1799567 2016-04-14 14:41:06 0
# 6 1799567 2016-04-14 17:51:06 1
# 7 2067650 2016-04-17 12:34:52 0
任何包中是否有任何函数可以计算一行中的 ID 在过去 x 小时内出现了多少次。我称之为 'velocity'.
我要计算的目标列用'VEL_7H'表示。也就是说,这个ID在过去7小时内出现了多少次?
ID TIME VEL_7H
1144727 2016-04-01 09:56:12 0
1144727 2016-04-01 15:16:03 1
1144727 2016-04-01 15:26:14 2
1144727 2016-04-02 09:48:48 0
1799567 2016-04-14 14:41:06 0
1799567 2016-04-14 17:51:06 1
2067650 2016-04-17 12:34:52 0
是否有使用时间和 ID 向量以及指定范围的函数给出 VEL_7H 列?
为了最大化性能,我认为Rcpp是合适的:
library(Rcpp);
df <- data.frame(ID=c(1144727L,1144727L,1144727L,1144727L,1799567L,1799567L,2067650L),TIME=as.POSIXct(c('2016-04-01 09:56:12','2016-04-01 15:16:03','2016-04-01 15:26:14','2016-04-02 09:48:48','2016-04-14 14:41:06','2016-04-14 17:51:06','2016-04-17 12:34:52')));
cppFunction('
IntegerVector countTrailingIDs(IntegerVector ids, DoubleVector times, double window ) {
IntegerVector res(ids.size());
for (int i = 0; i < ids.size(); ++i) {
int id = ids[i];
double trailTime = times[i]-window;
for (int j = i-1; j >= 0 && ids[j] == id && times[j] >= trailTime; --j)
++res[i];
}
return res;
}
');
df$VEL_7H <- countTrailingIDs(df$ID,df$TIME,60*60*7);
df;
## ID TIME VEL_7H
## 1 1144727 2016-04-01 09:56:12 0
## 2 1144727 2016-04-01 15:16:03 1
## 3 1144727 2016-04-01 15:26:14 2
## 4 1144727 2016-04-02 09:48:48 0
## 5 1799567 2016-04-14 14:41:06 0
## 6 1799567 2016-04-14 17:51:06 1
## 7 2067650 2016-04-17 12:34:52 0
注意函数需要ids
和times
先id后time排序
我们可以在 base R 中使用经典的拆分-应用-组合方法,首先按 ID 拆分数据框,将过去 7 小时内的条目数量相加,然后创建一个包含以下值的新列:
sdf <- split(df, df$ID)
last7 <- function(df) sapply(1:nrow(df), function(i) sum(df[i, "TIME"] - df[1:i, "TIME"] <= 60*60*7) - 1L)
df$VEL_7H <- unlist(sapply(sdf, last7))
df
# ID TIME VEL_7H
# 1 1144727 2016-04-01 09:56:12 0
# 2 1144727 2016-04-01 15:16:03 1
# 3 1144727 2016-04-01 15:26:14 2
# 4 1144727 2016-04-02 09:48:48 0
# 5 1799567 2016-04-14 14:41:06 0
# 6 1799567 2016-04-14 17:51:06 1
# 7 2067650 2016-04-17 12:34:52 0