rif-statementconditional-operator

Multiple conditions


I'm trying to make multiple conditions:

adae <- adae %>%
  mutate(AREPIOD = if_else((AESTDTC >= AP01SDT) & (AESTDTC <= AP01EDT), 1, 
                           if_else((AESTDTC >= AP02SDT) & (AESTDTC <= AP02EDT), 2, "")))

But I get the error:

Caused by error in `if_else()`:
! Can't combine `true` <double> and `false` <character>.

Please help. Where is the problem?


Solution

  • Unlike base R's ifelse, the type of the "true" and "false" arguments in dplyr's if_else must agree. In your case, you are trying to get your inner if_else to return either a number 2, or the empty string "". Since the output of if_else is a vector, it is unclear whether you want a numeric vector or a character vector.

    Base R's ifelse will simply convert the numbers to characters here:

    ifelse(c(TRUE, TRUE, FALSE), 2, "")
    #> [1] "2" "2" "" 
    

    But this may not be what you wanted. You can't do any maths on the output, for example, since the "2" values in the above are character strings. if_else forces you to decide what you mean, to avoid such ambiguity:

    if_else(c(TRUE, TRUE, FALSE), 2, "")
    #> Error in `if_else()`:
    #> ! Can't combine `true` <double> and `false` <character>.
    #> Run `rlang::last_trace()` to see where the error occurred.
    

    If we really want a character vector, we need to explicitly make the 2 appear as a character string for if_else to work:

    if_else(c(TRUE, TRUE, FALSE), "2", "")
    #> [1] "2" "2" "" 
    

    My guess though is that in your case, you want a numeric vector, with "" representing a missing value. It can be difficult to get away from this if you are used to spreadsheets, but missing numeric values in R must be recorded as NA, otherwise the vector gets converted to the wrong type. So it might be better to have:

    if_else(c(TRUE, TRUE, FALSE), 2, NA)
    #> [1]  2  2 NA
    

    In your case, therefore, you need to decide whether you want

    adae <- adae %>%
      mutate(AREPIOD = if_else((AESTDTC >= AP01SDT) & (AESTDTC <= AP01EDT), "1", 
                               if_else((AESTDTC >= AP02SDT) & (AESTDTC <= AP02EDT), "2", "")))
    

    or

    adae <- adae %>%
      mutate(AREPIOD = if_else((AESTDTC >= AP01SDT) & (AESTDTC <= AP01EDT), 1, 
                               if_else((AESTDTC >= AP02SDT) & (AESTDTC <= AP02EDT), 2, NA)))
    

    Either will work, but the type of output is up to you.