转向 for 循环以应用

Turning for loop to apply

我试图了解 apply 的工作原理,但很难理解如何使用它。 我有一个名为 SSO9 的 df 帧,它是 172*92。它只有 1:s 或 0:s 作为其中的元素。

Col1 Col2 Col3 ...
1      0    1
0      1    1
0      0    1
.
.

我现在想在选择三列时采用每个排列并采用行和。意思首先是第一列,第二列和第三列,然后取行总和并将其保存在新的 df 中,然后是第一列和第四列,依此类推。这意味着这将导致 92 选择 3 = 125580 列。

ds=data.frame(rowSums(SSO9[,c(1,2,3)]))

for(i in 1:90){
  for(j in (i+1):91){ 
    for(k in (j+1):92){
    temp<-data.frame(rowSums(SSO9[,c(i,j,k)]))
    colnames(temp)<-(paste(colnames(SSO9[i]),colnames(SSO9[c(j)]),paste(colnames(SSO9[k]),sep=",")))
    ds=cbind(ds,temp) 
    rm(temp)
    }
  }
}
ds$rowSums.SSO9...c.1..2..3...<-NULL

此代码有效但有点慢,所以我想尝试使用 apply insted of 3 for 循环,但我不知道如何使用 apply,尤其是当我需要所有排列时。同样如您所见,我创建了 df ds,方法是获取前三列的行和,然后将其删除,只是为了获得正确的维度,但可能有更好的方法来做到这一点。

我建议的第一件事是将输入存储为矩阵,因为它只有 1 和 0,并且这些类型的数值运算通常在矩阵上比 data.frames 更高效。

以下是如何使用 combn(), apply(), and rowSums() 完成此操作:

set.seed(1);
NR <- 172; NC <- 92; SSO9 <- matrix(sample(0:1,NR*NC,replace=T),NR,dimnames=list(NULL,paste0('Col',1:NC)));
head(SSO9[,1:10]);
##      Col1 Col2 Col3 Col4 Col5 Col6 Col7 Col8 Col9 Col10
## [1,]    0    1    1    1    0    0    0    1    1     0
## [2,]    0    0    0    1    1    0    1    1    1     1
## [3,]    1    0    0    0    0    1    1    1    0     0
## [4,]    1    1    0    1    1    0    0    1    1     0
## [5,]    0    1    0    1    1    0    0    0    1     1
## [6,]    1    1    1    1    1    0    1    1    1     0
system.time({
    comb <- combn(ncol(SSO9),3);
    res <- apply(comb,2,function(cis) rowSums(SSO9[,cis]));
    colnames(res) <- apply(comb,2,function(cis) paste(colnames(SSO9)[cis],collapse=','));
});
##    user  system elapsed
##   3.422   0.203   3.626
dim(res);
## [1]    172 125580
head(res[,1:10]);
##      Col1,Col2,Col3 Col1,Col2,Col4 Col1,Col2,Col5 Col1,Col2,Col6 Col1,Col2,Col7 Col1,Col2,Col8 Col1,Col2,Col9 Col1,Col2,Col10 Col1,Col2,Col11 Col1,Col2,Col12
## [1,]              2              2              1              1              1              2              2               1               2               2
## [2,]              0              1              1              0              1              1              1               1               0               0
## [3,]              1              1              1              2              2              2              1               1               2               2
## [4,]              2              3              3              2              2              3              3               2               3               3
## [5,]              1              2              2              1              1              1              2               2               1               1
## [6,]              3              3              3              2              3              3              3               2               2               2

另请注意,这些是 combinations, not permutations,因为顺序无关紧要。