仅供参考,这里是一个可以说是比较合适的基准:
library(data.table)
library(dplyr)
library(microbenchmark)
DT = data.table(id=seq(1e5))[,
.(source = c(if (runif(1) > .5) "A", if (runif(1) > .5)"B")), by=id]
DF = data.frame(DT)
microbenchmark(
dplyr =
DF %>% group_by(id) %>% mutate(gr = if(n()>1) "both" else as.character(source)),
dplyr_dt =
DT %>% group_by(id) %>% mutate(gr = if(n()>1) "both" else as.character(source)),
ave = DF$gr <-
ave(as.character(DF$source), DF$id, FUN = function(x) if(length(x) > 1) "both" else x),
dt = DT[, gr := if (.N > 1) "both" else as.character(source), by=id],
dt2 = DT[,
gr := as.character(source)][ DT[, if (.N > 1) 1, by=id][, V1 := NULL],
gr := "both", on = "id"],
times=10)
结果:
Unit: milliseconds
expr min lq mean median uq max neval
dplyr 1200.13579 1215.56997 1328.73931 1245.81556 1252.66023 1828.02921 10
dplyr_dt 38.43108 41.58004 47.98858 43.89661 49.27464 68.64005 10
ave 149.67549 153.03421 167.09148 163.19261 181.60074 191.22481 10
dt 32.31500 33.60741 41.00644 35.80188 37.60350 65.76292 10
dt2 25.99567 26.44592 28.11141 28.19138 28.55474 31.42691 10
我不知道为什么ave
做得更糟在这里。也许这是因为@bunk说,ave
不能很好地扩展到很多团体。 Dplyr在data.frame上速度较慢,但在使用data.table后端(如所宣传的)时速度更快。
对于它的价值,我的data.table解决方案是一个有点不同(证明一个单独的答案?):
DT[,
gr := as.character(source)
][DT[, if (.N > 1) 1, by=id][, V1 := NULL],
gr := "both"
, on = "id"]
首先,它gr
等于给source
,然后将其与both
代替它那些有两排的组。
nvm我说过,''ave'运行时间的一半以上都花在'交互'上 – jenesaisquoi
对于任何人都注意:对此感到抱歉。我有一个或两个错误。除了现在我们可以看到dplyr在data.frame上很慢之外,结果没有实质性改变。正如dplyr人们所说,如果你需要速度,你可以使用带有data.table“后端”的dplyr。 – Frank