我编写了一些代码来计算数据集中所有id对之间的相关性。输入和输出格式如下所示:
Input: obsid | varid | value
Output: obsid1 | obsid2 | correl
我意识到相关和所有对功能都可用,并在之前讨论过。这可能有所不同,因为我使用键/值或深度格式进行输入和输出。此外,我需要解决的实例有大约200,000个观测值和~500个密度为20%的变量。实际上,我需要计算4 x 10 ^ 10个相关性!所以,我希望能够提高效率。
这是创建实例的代码:
require(data.table)
CreateInstance <- function(nobs,nvar,density) {
dtbl <- data.table(
do.call("rbind",
lapply(1:nobs, function(n) {
v <- which(runif(nvar)<density)
if(length(v)>0) {cbind(n,v)}
})
)
)
setnames(dtbl, c("obsid","varid"))
dtbl$value <- as.numeric(sample(1:50, nrow(dtbl), replace=TRUE))
return(dtbl)
}
代码运行如下:
set.seed(100)
nobs <- 10
nvar <- 4
dens <- .5
inst <- CreateInstance(nobs,nvar,dens)
计算1次观察的所有相关性并选择前N
的代码GetCorrelationsForObs <- function(n) {
dtbl <- inst[inst[obsid==n,2:3,with=FALSE]][, list(sumxy=sum(value*i.value)), by=obsid]
if(nrow(dtbl)==0) {return(data.table(obsid1=integer(0),obsid2=integer(0),correl=numeric(0)))}
dtbl <- inst.summ[dtbl][obsid!=n]
infoy <- inst.summ[obsid==n,c(sumx,sdx)]
dtbl <- dtbl[, list(obsid2=obsid,
correl=(nvar*sumxy-infoy[1]*sumx)/(infoy[2]*sdx))][!is.na(correl),][order(-rank(correl))]
return(if(nrow(dtbl)>nbors) cbind(obsid1=n,dtbl[1:nbors]) else cbind(obsid1=n,dtbl))
}
此代码使用
运行inst.summ <- inst[, list(sumx=sum(value), sdx=sqrt(nvar*sum(value^2)-sum(value)^2)), by="obsid"]
nbors <- 2
setkey(inst,varid)
setkey(inst.summ,obsid)
correl.dt <- data.table(do.call("rbind", lapply(1:nobs, GetCorrelationsForObs) ))
对于较大的实例nobs <- 200000
,nvar <- 500
,dens <- .2
,nbors <- 100
,50次调用需要38秒才能GetCorrelationsForObs
。
问题:我意识到问题是embarrassingly parallel,我可以轻松地并行运行它。我正在寻找有关如何让GetCorrelationsForObs
更快运行的输入。这是我第一次使用data.table并想了解它是否可以运行得更快(不同的键?其他选项?)。感谢。