确定R中data.table中每行的值(X)与组(Y)中相同变量(X)的后续值之间的最大正差的最有效方法是什么。
示例:
set.seed(1)
dt <- data.table(X = sample(100:200, 500455, replace = TRUE),
Y = unlist(sapply(10:1000, function(x) rep(x, x))))
这是我认为无效且缓慢的解决方案:
dt[, max_diff := vapply(1:.N, function(x) max(X[x:.N] - X[x]), numeric(1)), by = Y]
head(dt, 21)
X Y max_diff
1: 126 10 69
2: 137 10 58
3: 157 10 38
4: 191 10 4
5: 120 10 75
6: 190 10 5
7: 195 10 0
8: 166 10 0
9: 163 10 0
10: 106 10 0
11: 120 11 80
12: 117 11 83
13: 169 11 31
14: 138 11 62
15: 177 11 23
16: 150 11 50
17: 172 11 28
18: 200 11 0
19: 138 11 56
20: 178 11 16
21: 194 11 0
如果您可以建议高效(更快)的解决方案?
答案 0 :(得分:3)
这是一个dplyr解决方案,速度提高了大约20倍,并且得到了相同的结果。我认为等效的data.table会更快。 (编辑:看到底部-是!)
加速来自减少需要执行的比较次数。始终会在组中剩余的最大数量上找到最大的差异,因此更快地首先识别该数字,并且每行只进行一次减法。
首先,原始解决方案在我的计算机上耗时约4秒钟:
tictoc::tic("OP data.table")
dt[, max_diff := vapply(1:.N, function(x) max(X[x:.N] - X[x]), numeric(1)), by = Y]
tictoc::toc()
# OP data.table: 4.594 sec elapsed
但是仅需0.2秒,我们就可以获取该data.table,转换为数据帧,添加orig_row
行号,按Y分组,按orig_row
反向排序,取X之间的差以及X,ungroup和按原始顺序重新排列的累积最大值:
library(dplyr)
tictoc::tic("dplyr")
dt2 <- dt %>%
as_data_frame() %>%
mutate(orig_row = row_number()) %>%
group_by(Y) %>%
arrange(-orig_row) %>%
mutate(max_diff2 = cummax(X) - X) %>%
ungroup() %>%
arrange(orig_row)
tictoc::toc()
# dplyr: 0.166 sec elapsed
all.equal(dt2$max_diff, dt2$max_diff2)
#[1] TRUE
编辑:正如@ david-arenburg在评论中所建议的那样,这可以在data.table中以闪电般的快速完成:
dt[.N:1, max_diff2 := cummax(X) - X, by = Y]
在我的计算机上,这比上述dplyr
解决方案快大约2-4倍。