【问题标题】:How to change matrix entries using conditional if in R如何在 R 中使用条件 if 更改矩阵条目
【发布时间】:2021-10-17 19:22:24
【问题描述】:

我有这个示例矩阵,我想根据条件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"

【问题讨论】:

    标签: r if-statement matrix conditional-statements multiple-entries


    【解决方案1】:

    这里不需要循环。只需在您对x&gt;5的调用中使用整个矩阵@

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

    这将对整个矩阵进行逻辑运算。但是,输出将是一个向量,它基本上是生成的逻辑矩阵,但从其dim 属性中剥离。

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

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

    【讨论】:

    • 它按我的意愿运行,它是最简单的代码,所以我接受这个
    【解决方案2】:

    失败原因

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

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

    您应该知道MAT 是数字,但是您在if...else... 语句中将字符分配给MAT,这将使MAT 转换为字符矩阵。在这种情况下,当您运行 MAT[i,j] &gt; 5 时,您会将一个字符与一个数值进行比较,例如,"18" &gt; 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"
    

    另类

    这个问题已经有很多答案了,下面是另一个base 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"
    

    【讨论】:

    • 也可以写成structure(as.character(...), dim = dim(MAT))array(as.character(...), dim = dim(MAT))
    • @Jean-ClaudeArbaut 是的,没错。
    • @Jean-ClaudeArbaut 你能否在这里查看我的帖子stackoverflow.com/questions/68793463/…,因为当我使用我制作的 r 函数中的代码时它不起作用
    【解决方案3】:

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

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

    -输出

    > 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" 
    

    【讨论】:

      【解决方案4】:

      试试这个:

      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" 
      

      【讨论】:

        【解决方案5】:

        更新: 在 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 所指出的,它将在第一次分配后强制转换为字符,这可能会导致下游操作出现意外结果。

        【讨论】:

        • 高度错误的代码。请注意,在第一条指令之后,MAT 是一个字符矩阵。然后,例如,"6e-12" &lt;= 5 为假。即使你没有无意中改变类型,这样写也是危险的。将“yes”替换为 1,将“no”替换为 0,再次失败。
        • 这将在第一次分配后强制转换为字符,这可能导致@Jean-ClaudeArbaut 和 ThomasIsCoding 观察到的下游操作中的意外结果
        • 感谢大家的意见。我已经更新了我的答案。请告诉我是否应该删除答案或者保留它以产生逆向学习效果。
        猜你喜欢
        • 2021-10-17
        • 1970-01-01
        • 2023-03-12
        • 1970-01-01
        • 1970-01-01
        • 2016-03-08
        • 1970-01-01
        • 1970-01-01
        • 2012-08-12
        相关资源
        最近更新 更多