转向 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,因为顺序无关紧要。
我试图了解 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,因为顺序无关紧要。