将函数应用于 R 中矩阵的每个单元格

Apply function to each cell of matrix in R

我正在尝试对 R 中数据 table 的每个单元格执行一个函数,根据此循环的结果创建第二个单元格。例如,假设我有矩阵 A

    Ad1    Ad2    Ad3    Ad4
    AA      6       0     10
    AB      7      10     12
    AC      0       0     15

我正在尝试创建矩阵 B

    Ad1    Ad2    Ad3    Ad4
    AA      1       0      1
    AB      1       0      1
    AC      0       0      1

如果每个单元格的值 > 0,则每个单元格都采用值 1 AND 列的总和减去该单元格也大于 0。

例如AA~Ad2为6,列之和为7(6 + 7 + 0 - 6);则矩阵 B 中的 AA~Ad2 取值 1.

有没有一种方法可以不执行循环来执行此操作?我已经设法用一个循环来做到这一点,但它花费的时间太长了:

A = read.table(text="Ad1    Ad2    Ad3    Ad4
AA     6      0     10
AA     7     10     12
AA     0     0     15", header=TRUE)

B = read.table(text="Ad1    Ad2    Ad3    Ad4
AA     0      0     0
AA     0     0     0
AA     0     0     0", header=TRUE)

for (i in 1:nrow(B)) {
    for (j in 2:ncol(B)) {
        if ((sum(A[,j], na.rm = T) - ifelse(is.na(A[i,j]), 0, A[i,j]))> 0 &
        ifelse(is.na(A[i,j]), 0, A[i,j]) > 0 ) 
        {B[i,j] <- 1}
    }
}

我们可以通过创建两个逻辑矩阵在没有循环的情况下做到这一点 -1) 检查数字列值是否大于 0 (A[-1] > 0),2) 检查列的差值是否与列值也大于0。如果两者都为TRUE(&条件),则将逻辑矩阵转换为二进制(+)并赋值给数据集的子集(A[-1])

A[-1] <-  +(colSums(A[-1])[col(A[-1])]-A[-1]>0 & A[-1] > 0)
A
#  Ad1 Ad2 Ad3 Ad4
#1  AA   1   0   1
#2  AB   1   1   1
#3  AC   0   0   1

这是另一种 base R 方法,分为 2 行。第一个拉出可以减少复制的矩阵。第二行计算结果,首先检查值是否大于 0,然后检查总的 colSum 是否大于每个元素。这部分是通过 rep 和每个参数部分完成的。

# extract matrix from data.frame
myMat <- as.matrix(A[-1])
# calculate result and store in data.frame
A[-1] <- (myMat > 0) * ((rep(colSums(myMat), each=nrow(myMat))- myMat) > 0)
A
  Ad1 Ad2 Ad3 Ad4
1  AA   1   0   1
2  AA   1   0   1
3  AA   0   0   1

这是一个使用两个逻辑表达式对原始矩阵求值的解决方案:

(A > 0 & (colSums(A) - A > 0)) * 1.0

& 的左侧检查值是否大于零,而右侧检查与列总和相关的要求。

它们各自生成一个与 A 维度相同的逻辑矩阵。然后,& 允许您组合逻辑矩阵以生成一个新矩阵,其中仅当单元格在两个输入矩阵中都为 TRUE 时单元格才为 TRUE。

最后,* 1.0 将逻辑矩阵转换为数字。

您还可以这样做:

m <- as.matrix(A[,-1])
colsm <- matrix(colSums(m), ncol = ncol(m), nrow = nrow(m), byrow = T)
(colsm-m)>0 & m>0)*1

#    Ad2 Ad3 Ad4
#[1,]   1   0   1
#[2,]   1   0   1
#[3,]   0   0   1