Ada*_*dam 7 performance loops r subset data.table
我在研究中遇到的反复分析范例是需要根据所有不同的组id值进行子集,依次对每个组进行统计分析,并将结果放在输出矩阵中以便进一步处理/总结.
我通常在R中执行此操作的方式如下:
data.mat <- read.csv("...")
groupids <- unique(data.mat$ID) #Assume there are then 100 unique groups
results <- matrix(rep("NA",300),ncol=3,nrow=100)
for(i in 1:100) {
tempmat <- subset(data.mat,ID==groupids[i])
# Run various stats on tempmat (correlations, regressions, etc), checking to
# make sure this specific group doesn't have NAs in the variables I'm using
# and assign results to x, y, and z, for example.
results[i,1] <- x
results[i,2] <- y
results[i,3] <- z
}
Run Code Online (Sandbox Code Playgroud)
这最终为我工作,但根据数据的大小和我正在使用的组的数量,这可能需要长达三天.
除了分支到并行处理之外,还有什么"技巧"可以让这样的东西运行得更快吗?例如,将循环转换为其他东西(类似于使用包含我想在循环中运行的统计数据的函数的应用),或者不需要实际将数据子集分配给变量?
也许这只是常识(或抽样错误),但我尝试在我的一些代码中使用括号进行子集化而不是使用子命令,它似乎提供了一些让我感到惊讶的性能提升.我使用了一些代码并使用与上面相同的对象名称输出如下:
system.time(for(i in 1:1000){data.mat[data.mat$ID==groupids[i],]})
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)user system elapsed 361.41 92.62 458.32
system.time(for(i in 1:1000){subset(data.mat,ID==groupids[i])})
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)user system elapsed 378.44 102.03 485.94
在其中一个答案中,jorgusch建议我使用data.table包来加速我的子集化.所以,我将它应用于我本周早些时候运行的一个问题.在一个略多于1,500,000行和4列(ID,Var1,Var2,Var3)的数据集中,我想计算每组中的两个相关性(由"ID"变量索引).有超过50,000个团体.下面是我的初始代码(与上面的代码非常相似):
data.mat <- read.csv("//home....")
groupids <- unique(data.mat$ID)
results <- matrix(rep("NA",(length(groupids) * 3)),ncol=3,nrow=length(groupids))
for(i in 1:length(groupids)) {
tempmat <- data.mat[data.mat$ID==groupids[i],]
results[i,1] <- groupids[i]
results[i,2] <- cor(tempmat$Var1,tempmat$Var2,use="pairwise.complete.obs")
results[i,3] <- cor(tempmat$Var1,tempmat$Var3,use="pairwise.complete.obs")
}
Run Code Online (Sandbox Code Playgroud)
我现在正在重新计算这个问题需要花费多长时间,但是从我记忆中来看,当我早上进入办公室并且在下午中午某个时间结束时,我开始运行它.图5-7小时.
重构我的代码以使用data.table ....
data.mat <- read.csv("//home....")
data.mat <- data.table(data.mat)
testfunc <- function(x,y,z) {
temp1 <- cor(x,y,use="pairwise.complete.obs")
temp2 <- cor(x,z,use="pairwise.complete.obs")
res <- list(temp1,temp2)
res
}
system.time(test <- data.mat[,testfunc(Var1,Var2,Var3),by="ID"])
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)user system elapsed 16.41 0.05 17.44
使用data.table将结果与使用for循环到所有ID和手动记录结果的结果进行比较,它们似乎给了我相同的答案(尽管我必须更彻底地检查一下).这似乎是一个非常大的速度提升.
使用子集运行代码最终再次完成:
Run Code Online (Sandbox Code Playgroud)user system elapsed 17575.79 4247.41 23477.00
我想看看是否有任何不同的方法使用了推荐的plyr包.这是我第一次使用它,所以我可能做得有些低效,但它仍然有助于与带有子集的for循环相比.
使用与以前相同的变量和设置......
data.mat <- read.csv("//home....")
system.time(hmm <- ddply(data.mat,"ID",function(df)c(cor(df$Var1,df$Var2, use="pairwise.complete.obs"),cor(df$Var1,df$Var3,use="pairwise.complete.obs"))))
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)user system elapsed 250.25 7.35 272.09
归档时间: |
|
查看次数: |
2465 次 |
最近记录: |