如何在r中使用条件if更改矩阵条目



我有这个示例矩阵,我想根据条件if语句用"YES""NO"更改矩阵的条目。

a<-c(5,1,0,3,2,0.6,1.6,7,9,0)
b<-c(11,0,1,18,11,11,0,13,20,10)
c<-c(10,20,0.7,0.8,0.3,0.4,0,0.9,1,1)
MAT<-cbind(a,b,c)
MAT
for (i in 1:nrow(MAT)){
for (j in 1:ncol(MAT)){
if (MAT[i,j]>5){
MAT[i,j]="YES"
} else {
MAT[i,j]="NO"
}
}
}
print(MAT)

我得到的输出是这样的,它是错误的。请帮忙告诉我出了什么问题,如何解决?

a     b    c   
[1,] "NO"  "NO" "NO"
[2,] "NO"  "NO" "NO"
[3,] "NO"  "NO" "NO"
[4,] "NO"  "NO" "NO"
[5,] "NO"  "NO" "NO"
[6,] "NO"  "NO" "NO"
[7,] "NO"  "NO" "NO"
[8,] "YES" "NO" "NO"
[9,] "YES" "NO" "NO"
[10,] "NO"  "NO" "NO"

这里不需要循环。只需在调用x>5时使用整个矩阵

ifelse(MAT>5, "YES", "NO")

这将对整个矩阵进行逻辑运算,并输出一个逻辑矩阵。

您可以使用空括号[]ifelse()的输出中重新分配VALUES,同时保留MATSTRUCTURE,如:

MAT[]<-ifelse(MAT>5, "YES", "NO")

故障原因

你尝试失败的原因来自这一部分:

if (MAT[i,j]>5){
MAT[i,j]="YES"
} else {
MAT[i,j]="NO"
}
}

您应该知道MAT是数字,但是您在if...else...语句中为MAT分配字符,这将使MAT转换为字符矩阵。在这种情况下,当你运行MAT[i,j] > 5时,你正在将一个字符与一个数值进行比较,例如,"18" > 5,它返回一个不希望的FALSE


解决方案

一个解决方法是使用另一个变量来存储if...else...之后的值,而不是替换MAT中的值:

a <- c(5, 1, 0, 3, 2, 0.6, 1.6, 7, 9, 0)
b <- c(11, 0, 1, 18, 11, 11, 0, 13, 20, 10)
c <- c(10, 20, 0.7, 0.8, 0.3, 0.4, 0, 0.9, 1, 1)
MAT <- cbind(a, b, c)
out <- MAT
for (i in 1:nrow(MAT)) {
for (j in 1:ncol(MAT)) {
if (MAT[i, j] > 5) {
out[i, j] <- "YES"
} else {
out[i, j] <- "NO"
}
}
}

,

> out
a     b     c
[1,] "NO"  "YES" "YES"
[2,] "NO"  "NO"  "YES"
[3,] "NO"  "NO"  "NO"
[4,] "NO"  "YES" "NO"
[5,] "NO"  "YES" "NO"
[6,] "NO"  "YES" "NO"
[7,] "NO"  "NO"  "NO"
[8,] "YES" "YES" "NO"
[9,] "YES" "YES" "NO"
[10,] "NO"  "YES" "NO"

选择

这个问题已经有很多答案了,下面是另一个基本的R选项

> `dim<-`(as.character(factor(MAT > 5, labels = c("NO", "YES"))), dim(MAT))
[,1]  [,2]  [,3]
[1,] "NO"  "YES" "YES"
[2,] "NO"  "NO"  "YES"
[3,] "NO"  "NO"  "NO"
[4,] "NO"  "YES" "NO"
[5,] "NO"  "YES" "NO"
[6,] "NO"  "YES" "NO"
[7,] "NO"  "NO"  "NO"
[8,] "YES" "YES" "NO"
[9,] "YES" "YES" "NO"
[10,] "NO"  "YES" "NO"

仅使用逻辑矩阵转换为数字索引

MAT[] <- c("NO", "YES")[1 + (MAT > 5)]

-ouptut

> MAT
a     b     c    
[1,] "NO"  "YES" "YES"
[2,] "NO"  "NO"  "YES"
[3,] "NO"  "NO"  "NO" 
[4,] "NO"  "YES" "NO" 
[5,] "NO"  "YES" "NO" 
[6,] "NO"  "YES" "NO" 
[7,] "NO"  "NO"  "NO" 
[8,] "YES" "YES" "NO" 
[9,] "YES" "YES" "NO" 
[10,] "NO"  "YES" "NO" 

试试这个:

apply(MAT, 2, function(x) ifelse(x > 5, "YES", "NO"))
a     b     c    
[1,] "NO"  "YES" "YES"
[2,] "NO"  "NO"  "YES"
[3,] "NO"  "NO"  "NO" 
[4,] "NO"  "YES" "NO" 
[5,] "NO"  "YES" "NO" 
[6,] "NO"  "YES" "NO" 
[7,] "NO"  "NO"  "NO" 
[8,] "YES" "YES" "NO" 
[9,] "YES" "YES" "NO" 
[10,] "NO"  "YES" "NO" 

更新:在Jean-Claude Arbaut, ThomasIsCoding和GuedesBF的帮助说明之后,请注意第一个答案是错误的,这里是dplyr的替代方案:

我们可以在将matrix更改为tibble类后使用across,并在操作后重新更改为matrix类:

library(tibble)
library(dplyr)
MAT <- MAT %>% 
as_tibble() %>% 
mutate(across(everything(), ~ifelse(. > 5, "YES", "NO"))) %>% 
as.matrix()

第一个答案:警告!

不要使用这个代码

MAT[MAT>5] <- "yes"
MAT[MAT<=5] <- "no"

正如Jean-Claude Arbaut, ThomasIsCoding和GuedesBF所指出的,它将在第一次赋值后强制字符,这可能导致下游操作中意想不到的结果。

最新更新