2016-08-19 47 views
3

我有數據,看起來像這樣:ifelse沒有結束行循環如預期

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) 

我試圖創造,如果有,如果沒有匹配或0返回1的新列。

我不工作的代碼如下所示:

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 

我已經看了帖子:

ifelse not working as expected in R

Loop over rows of dataframe applying function with if-statement

,但我無法得到任何回答我的問題。

回答

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

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

同樣地,在所有的所有列,有1 ,因此所有ifelse將返回TRUE,結果爲值1.

wh ereas相反

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

返回邏輯矢量具有相同length爲原始列。從本質上說,通過使用%in%,返回的長度將在lhs%in%


ifelse它不是必需的,更好的選擇是基於對象的length,在邏輯使用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 
0

而不是單獨使用ifelse每列可以檢查行明智的,如果存在整行1,然後返回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