【发布时间】:2019-11-26 20:43:24
【问题描述】:
我需要估计不同组内的一些统计数据。我的实际数据集有超过 1000 万行。
使用 for 循环很容易做到这一点。但是,我尝试使用 data.table 来做同样的事情。但是,与 for 循环相比,它的速度非常慢。
library("data.table")
set.seed(1234) # reproducibility
dt1 <- data.table(id=rep(letters[1:5], rep(10,5)), group=1:10, value=rnorm(100))
# Method 1: using for loops
loopFUN <- function(DT){
Out1 <- list()
idx <- 1
for(i in unique(DT$id)){
for(g in unique(DT$group)){
sub.g <- subset(DT, group==g)
sub.i.g <- subset(sub.g, id==i)
vt <- var.test(x=sub.i.g$value, y=sub.g$value, alternative="greater", ratio=1)
Out1[[idx]] <- c(i, g, vt$statistic, sqrt(vt$estimate),vt$p.value)
idx <- idx + 1
}
}
Out1 <- data.table(do.call(rbind, Out1))
colnames(Out1) <- c("id","group","F.Stat","SD.Ratio","P.value")
return(Out1)
}
# Method 2: using a function inside tada.table
dtFUN <- function(DT){
test <- function(x, y){
VT <- var.test(x, y, alternative="greater", ratio=1)
res <- c(F.Stat=VT$statistic, SD.Ratio=sqrt(VT$estimate), P.value=VT$p.value)
return(res)
}
setkey(DT, id, group)
Out2 <- DT[, {x=value; DT[, list(g2=group, vt=test(x, value)), by=group]}, by=.(id,group)]
Out2 <- subset(Out2, group==g2)[, .(id, group, g2=rep(1:3,50), vt)]
Out2 <- dcast(Out2, id + group ~ g2, value.var = "vt")
colnames(Out2) <- c("id","group","F.Stat","SD.Ratio","P.value")
return(Out2)
}
LP <- loopFUN(dt1)
DT <- dtFUN(dt1)
all(LP==DT)
library("microbenchmark")
compare <- microbenchmark(LP <- loopFUN(dt1),
DT <- dtFUN(dt1),
times = 100)
# Results
expr min lq mean median uq max neval cld
LP <- loopFUN(dt1) 42.80655 45.33526 47.35974 46.2085 47.90351 88.42227 100 a
DT <- dtFUN(dt1) 140.41182 145.26643 152.61285 149.7490 154.57031 276.77088 100 b
我可以得到正确的结果。但我正在努力加快其性能。我想知道是否有人可以给我一些关于如何让它更快的建议。谢谢。
【问题讨论】:
-
我的实际数据集有超过1000万行。
标签: r loops for-loop data.table