如何加快我的R代码?

时间:2018-07-12 14:25:34

标签: r performance vectorization

我在编写代码时遇到了一些麻烦,需要花费大量时间才能运行。

for (k in 1:length(df_2L)) { 
  mat = matrix(99,nrow=dim(df_2L[[k]])[1],ncol= (dim(df_2L[[k]])[1]))
  for(j in 1:dim(df_2L[[k]])[1]) {
    for(i in 1:dim(df_2L[[k]])[1]) {
      if (df_2L[[k]][j] == df_2L[[k]][i]) {mat[i,j]<-1} 
      else {mat[i,j]<-0}
      }
    }
  assign(paste0("mat_2L_",k),mat)
  }

matall_2L_coassign <- lapply(ls(pattern="mat_2L_"),get)
matSum2L_coassign<-Reduce('+',matall_2L_coassign)

write.table(matSum2L_coassign,"matSum2L_coassign.txt",
            quote=F,row.names=F,col.names=F,dec=".",sep="\t")

请注意:

length(df_2L)[1]  
#[1] 38

dim(df_2L[[k]])[1] 
#[1] 503

一天后...

有关我的数据结构的一些信息:

str(lapply(df_2L[1:2], head))
List of 2
 $ :Classes 'data.table' and 'data.frame':  6 obs. of  1 variable:
  ..$ V1: int [1:6] 1 1 1 1 1 1
  ..- attr(*, ".internal.selfref")=<externalptr> 
 $ :Classes 'data.table' and 'data.frame':  6 obs. of  1 variable:
  ..$ V1: int [1:6] 1 1 1 1 1 1
  ..- attr(*, ".internal.selfref")=<externalptr> 

1 个答案:

答案 0 :(得分:3)

似乎df_2L是一维数组(长度为38,长度为38 503)的列表。


在循环嵌套中,代码优化应从内层开始到外层。您可以替换

mat = matrix(99,nrow=dim(df_2L[[k]])[1],ncol= (dim(df_2L[[k]])[1]))
for(j in 1:dim(df_2L[[k]])[1]) {
  for(i in 1:dim(df_2L[[k]])[1]) {
    if (df_2L[[k]][j] == df_2L[[k]][i]) {mat[i,j]<-1} 
    else {mat[i,j]<-0}
    }
  }

通过矢量化的野兽:

mat <- outer(df_2L[[k]], df_2L[[k]], "==") + 0

通过将==outer一起使用,您将得到FALSE / TRUE逻辑矩阵,然后+ 0将其强制为0/1二进制矩阵。


现在,转换后的代码只有一个循环。

for (k in 1:length(df_2L)) {
  mat <- outer(df_2L[[k]], df_2L[[k]], "==") + 0
  assign(paste0("mat_2L_",k),mat)
  }

matall_2L_coassign <- lapply(ls(pattern="mat_2L_"),get)

很明显,您最终希望将所有临时结果收集到一个列表中。然后,为什么不直接使用lapply

matall_2L_coassign <- lapply(df_2L, function (x) outer(x, x, "==") + 0L)

与计算相关的最终问题是

matSum2L_coassign <- Reduce('+', matall_2L_coassign)

这实际上足够好。


最终代码:

matall_2L_coassign <- lapply(df_2L, function (x) outer(x, x, "==") + 0L)
matSum2L_coassign <- Reduce('+', matall_2L_coassign)
write.table(matSum2L_coassign,"matSum2L_coassign.txt",
            quote=F,row.names=F,col.names=F,dec=".",sep="\t")

一天后...

感谢您在数据结构中发布信息。因此,您实际上有一个数据表列表。在这种情况下,我们必须首先将其强制转换为向量列表(或一维数组)。

## extract first variable of a data frame / table into a vector
df_2L <- lapply(df_2L, "[[", 1)

然后您可以使用我上面的答案。