如何有效确定每行中的变量值与R中data.table中的相同变量后继行值之间的最大差

时间:2019-01-19 22:08:35

标签: r algorithm dplyr data.table

确定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

如果您可以建议高效(更快)的解决方案?

1 个答案:

答案 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倍。