ifelse没有按预期循环遍历行

时间:2016-08-19 10:20:46

标签: r

我的数据如下:

 df <- read.table(tc <- textConnection("
     var1    var2    var3    var4
      1       1       7      NA
      4       4       NA      6
      2       NA      3       NA                
      4       4       4       4              
      1       3       1      1"), header = TRUE); close(tc)

我试图创建一个新列,如果匹配则返回1,否则返回0。

我的非工作代码如下所示:

 df$var5 = ifelse("1" %in% df$var1,1,
                ifelse("1" %in% df$var2,1,
                      ifelse("1" %in% df$var3,1,
                           ifelse("1" %in% df$var4,1,0))))
给我一张桌子:

 var1    var2    var3    var4   var5
      1       1       7      NA      1
      4       4       NA      6      1
      2       NA      3      NA      1         
      4       4       4       4      1        
      1       3      1        1      1

我真正想要的表应该看起来像

    var1    var2    var3    var4   var5
      1       1       7      NA      1
      4       4       NA      6      0
      2       NA      3      NA      0         
      4       4       4       4      0        
      1       3      1        1      1

我看过这些帖子:

https://jsfiddle.net/6ktgc4h9/5/

ifelse not working as expected in R

但我无法解决我的问题。

2 个答案:

答案 0 :(得分:2)

正确的方法应该是

with(df, ifelse(var1 %in% 1,1,
            ifelse(var2 %in% 1,1,
                  ifelse(var3 %in% 1,1,
                       ifelse(var4 %in% 1,1,0)))))
#[1] 1 0 0 0 1

原因是1 %in% df1$var1只返回单个元素1。

1 %in% df$var1
#[1] TRUE

同样,在所有列中都有1,因此它将为所有ifelse返回TRUE,从而产生值1.

而相反

df$var1 %in% 1
#[1]  TRUE FALSE FALSE FALSE  TRUE

返回与原始列具有相同length的逻辑向量。实质上,通过使用%in%,返回的长度将基于length lhs中对象的%in%

不需要ifelse,更好的选择是,在逻辑矩阵(rowSum)上使用df ==1,并检查它是否不等于0,转换使用as.integer二进制文件。

as.integer(rowSums(df == 1, na.rm =TRUE)!=0)
#[1] 1 0 0 0 1

或另一个选项Reduce |

as.integer(Reduce(`|`, lapply(replace(df, is.na(df), 0), `==`, 1)))
#[1] 1 0 0 0 1

答案 1 :(得分:1)

如果整个行中存在1,则可以逐行检查,而不是分别对每列使用ifelse,然后相应地返回1或0

as.numeric(apply(df, 1, function(x) any(x == 1)) %in% TRUE) 
#[1] 1 0 0 0 1

只是为了更好地解释这些步骤:

apply(df, 1, function(x) any(x == 1))
#[1]  TRUE    NA    NA FALSE  TRUE

apply(df, 1, function(x) any(x == 1)) %in% TRUE
#[1]  TRUE FALSE FALSE FALSE  TRUE

as.numeric(apply(df, 1, function(x) any(x == 1)) %in% TRUE)
#[1] 1 0 0 0 1