将函数应用于 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
我正在尝试对 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