在 R 中迭代条件和

Iterating conditional sums in R

我有一系列包含 1 和 0 的二维数值矩阵。 (所以我想它们也可以被视为逻辑数组。)我希望能够为此类数组做的是生成一个向量,其长度为数组的一维长度(列数)。对于数组中的每一列,它将包含条目为 1 的行的行总和。

这是我对单列的看法:

#Generate sample data
dataset<-matrix(sample(0:1, size=190, replace=TRUE), nrow=19, ncol=10)
#Calculate row sums
scores<-rowSums(dataset)
#calculate desired statistic for column 1
M1_1 <- sum(scores[which (dataset[,1]==1)])
#calculate same statistic for column 2
M1_2 <- sum(scores[which (dataset[,2]==1)])

显然,我不想写 M1_1、M1_2、...、M1_n,而是想定义 M1_X 来遍历每一列。我怀疑这是一件非常简单的事情,但一直无法弄清楚如何去做。任何指导将不胜感激。

我们可以用 sapply 循环并得到 sum

as.vector(sapply(split(dataset, col(dataset)), function(x) sum(scores[x==1])))
#[1] 56 47 50 53 55 48 75 67 40 55

或使用apply

apply(dataset, 2, function(x) sum(scores[x==1]))
#[1] 56 47 50 53 55 48 75 67 40 55

或者矢量化方法是复制 'scores' 并将其与 'dataset' 相乘,而不使用任何回收(这有时很危险)

colSums(scores[row(dataset)]*dataset)
#[1] 56 47 50 53 55 48 75 67 40 55

或者另一个直观的选择是 sweep

colSums(sweep(dataset, 1, scores, FUN = "*"))
#[1] 56 47 50 53 55 48 75 67 40 55

基于 OP 的 post、

M1_1
#[1] 56
M1_2
#[1] 47

或者正如@user20650 评论的那样,一个简洁的选项是crossprod

crossprod(scores, dataset)

或者在不同的步骤中甚至不计算 'scores'

rowSums(crossprod(dataset))
#[1] 56 47 50 53 55 48 75 67 40 55

我们可以将 0 和 1 的矩阵与相应的分数相乘,然后按列求和

colSums(dataset * scores)

#[1] 44 58 50 53 42 60 43 46 55 45

矩阵乘法也可以工作(可用种子 123 重现):

as.numeric(matrix(scores, nrow=1) %*% dataset)
# [1] 53 72 16 51 43 49 51 49 30 66