我正在使用一个模拟数据集,其中包含许多组(+2百万),我想计算每个组的观测总数以及超过阈值(这里是2)的观测数量。
当我创建一个标志变量时,似乎速度更快,特别是对于dplyr
来说,而对于data.table
也稍微快一点。
为什么会这样?在每种情况下它是如何背后工作的?
请查看下面的示例。
模拟数据集
# create an example dataset
set.seed(318)
N = 3000000 # number of rows
dt = data.frame(id = sample(1:5000000, N, replace = T),
value = runif(N, 0, 10))
使用dplyr
library(dplyr)
# calculate summary variables for each group
t = proc.time()
dt2 = dt %>% group_by(id) %>% summarise(N = n(),
N2 = sum(value > 2))
proc.time() - t
# user system elapsed
# 51.70 0.06 52.11
# calculate summary variables for each group after creating a flag variable
t = proc.time()
dt2 = dt %>% mutate(flag = ifelse(value > 2, 1, 0)) %>%
group_by(id) %>% summarise(N = n(),
N2 = sum(flag))
proc.time() - t
# user system elapsed
# 3.40 0.16 3.55
Using data.table
library(data.table)
# set as data table
dt2 = setDT(dt, key = "id")
# calculate summary variables for each group
t = proc.time()
dt3 = dt2[, .(N = .N,
N2 = sum(value > 2)), by = id]
proc.time() - t
# user system elapsed
# 1.93 0.00 1.94
# calculate summary variables for each group after creating a flag variable
t = proc.time()
dt3 = dt2[, flag := ifelse(value > 2, 1, 0)][, .(N = .N,
N2 = sum(flag)), by = id]
proc.time() - t
# user system elapsed
# 0.33 0.04 0.39
data.table
中,sum(var)
和.N
被进行了gforce优化,但sum(expr)
还没有进行优化。添加verbose = TRUE
参数,查看优化表达式的不同之处。我们将来会更好地处理这些情况。 - Arundata.table
中,我怀疑一个区别是第二个实例中的数据表已经排序,因此您没有计算它。尝试在每个实例上方放置dt2 = setDT(dt, key = "id")
。 - lmodata.table
实例中提供了相对较小的加速,从经过时间=2.30到经过时间=1.95。 - lmoflag := value > 2
)将进一步提高速度。 - Jaap