【问题标题】:How do I optimize a nested for loop using data.table?如何使用 data.table 优化嵌套 for 循环?
【发布时间】:2014-06-10 16:12:28
【问题描述】:

我有兴趣使用 data.table 优化一些代码。我觉得我应该能够比我目前的解决方案做得更好,并且它不能很好地扩展(随着行数的增加)。

假设我有一个值矩阵,ID 表示人,其余值是特征(在我的例子中是血统)。我想创建一个逻辑矩阵,它反映两个 ID(行)是否在其行(包括 ID)之间共享任何值。我最近一直在使用 data.table,但我无法弄清楚如何更有效地做到这一点。我已经尝试(但失败了)嵌套应用语句,或者以某种方式使用 data.table 的 .SD 函数来完成此操作。

工作代码如下。

m <- matrix(rep(1:10,2),nrow=5,byrow=T)
m[c(1,3),3:4] <- NA
dt <- data.table(m)
setnames(dt,c("id","v1","v2","v3"))
res <- matrix(data=NA,nrow=5,ncol=5)
dimnames(res) <- list(dt[,id],dt[,id])
for (i in 1:nrow(dt)){
  for (j in i:nrow(dt)){
    res[j,i] <- res[i,j] <-length(na.omit(intersect(as.numeric(dt[i]),as.numeric(dt[j])))) > 0 
  }
}
res

【问题讨论】:

  • 看看outer 是否可以提供任何速度提升。类似outer(1:nrow(m), 1:nrow(m), Vectorize(function(x, y) length(na.omit(intersect(m[x, ], m[y, ]))) &gt; 0))
  • 您能否提供更多详细信息:矩阵中的值是整数/双精度/字符;矩阵的大小是多少;矩阵中唯一值的数量是多少?
  • 在发布的示例中,所有值都是整数,矩阵 (m) 是 5x5。在我的真实数据中,值是字符,矩阵是 710x710。我想我可以根据我的真实数据调整示例的解决方案,希望我做得足够小/通用,其他人可能会觉得它有用。

标签: r for-loop data.table apply


【解决方案1】:

不久前我遇到了类似的问题,有人帮助了我。这是转换为您的问题的帮助...

tm<-t(m) #transpose the matrix
dtt<-data.table(tm[2:4,]) #take values of matrix into data.table
setnames(dtt,as.character(tm[1,])) #make data.table column names
comblist<-combn(names(dtt),2,FUN=list) #create list of all possible column combinations
preresults<-dtt[,lapply(comblist, function(x)     length(na.omit(intersect(as.numeric(get(x[1])),as.numeric(get(x[2]))))) > 0)] #recreate your double for loop
preresults<-melt(preresults,measure.vars=names(preresults)) #change columns to rows
preresults[,c("LHS","RHS"):=lapply(1:2,function(i)sapply(comblist,"[",i))] #add column labels
preresults[,variable:=NULL] #kill unneeded column

关于如何让我的preresults 与您的res 具有相同的格式,我对此一无所知,但这应该可以为您带来所需的性能提升。

【讨论】:

    猜你喜欢
    • 2012-01-27
    • 2020-05-18
    • 1970-01-01
    • 1970-01-01
    • 2017-05-28
    • 1970-01-01
    • 1970-01-01
    • 2020-09-07
    相关资源
    最近更新 更多