Thomas
Thomas

Reputation: 2534

Trouble with >= and ifelse in R

This is related to a previous question at R: How to include NA in ifelse?. I am trying to create a column ID based on logical tests using values from a number of different columns. For the following example dataframe:

test2 <- structure(list(time1 = c(10L, 20L, NA, NA), time2 = c(5L, NA, 
10L, NA), size = 1:4, type = structure(1:4, .Label = c("A", "B", 
"C", "D"), class = "factor"), ID = c("6", "6", NA, NA)), .Names = c("time1", 
"time2", "size", "type", "ID"), row.names = c(NA, -4L), class = "data.frame")

which looks like

    time1   time2   size    type    
1   10      5       1       A       
2   20      NA      2       B      
3   NA      10      3       C      
4   NA      NA      4       D     

I want to create a column ID containing a value of 6 when the following conditions are met: 1) either time1 or time2 is not NA, 2) size is greater or equal to 2, and 3) type is not equal to C or D. I have been trying the following code:

test2$ID <- ifelse(is.na(test2$time1) & is.na(test2$time2) & test2$size >= 2 | test2$type %in% "C" | test2$type %in% "D", NA, "6")

For some reason, the "greater than or equal to 2" statement is not working properly. This code gives me the solution

time1   time2   size    type    ID
1   10      5       1       A       6
2   20      NA      2       B       6
3   NA      10      3       C       NA
4   NA      NA      4       D       NA

However, the solution I need should be

time1   time2   size    type    ID
1   10      5       1       A       NA
2   20      NA      2       B       6
3   NA      10      3       C       NA
4   NA      NA      4       D       NA

Can anyone tell me what I am doing wrong?

Also: I am having a hard time understanding how logical operators work in R. It seems these are evaluated sequentially, so that X & Y | Z is not equivalent to Z | X & Y. Is this correct? Could I make a statement link (X & Y) | Z and this would be equivalent to Z | (X & Y)? Sorry for the silly question!

Upvotes: 0

Views: 281

Answers (1)

Rorschach
Rorschach

Reputation: 32426

test2$ID <- with(test2, ifelse( (!is.na(time1) | !is.na(time2)) &
                   size >= 2 &
                   !type %in% c("C", "D"), 6, NA))

Yes like you said you can use parentheses to force & to evaluate before |.

Upvotes: 4

Related Questions