Trouble with if statement

I've tried about every way I know to make this work as an if or ifelse with no avail....

I'm trying to conditionally fix the NA values in status. If status is NA, we need to check the room column. From there, if room has a non-NA value, status should be "approved", else status should be changed from NA to "denied".

id status room
12345 approved 5
67890 denied NA
13579 approved 7
24680 denied NA
80642 NA 3
97531 NA 2
90876 NA NA
54321 denied NA

My last attempt looked like this

if(is.na(p$status) && is.na(p$room)){
    p$status <- "denied"
} else if(is.na(p$status) && !is.na(p$room)){
   p$status <- "approved"
} else {
    p$status <- p$status
}

I'm sure the answer's right in front of my nose just past the cloud of hours of frustration. Thank you in advance for any help.

Hi, first I want to talk about why your solution isn't working and then help find a better one. It's important to remember that R takes advantage of vectors.

When you come across your first if statement r is.na(p$status) && is.na(p$room), it evaluates to FALSE so the next statement is checked. r is.na(p$status) && !is.na(p$room) also evaluates to FALSE so the final else is run and the only statement run is r p$status <- p$status so everything stays the same as you're seeing!

I suggest using dplyr to help with this as follows:

library(tidyverse)
    
    p <- tribble(
        ~id,    ~status,    ~room,
        12345,  'approved', 5,
        67890,  'denied',   NA,
        13579,  'approved', 7,
        24680,  'denied',   NA,
        80642,  NA_character_,  3,
        97531,  NA_character_,  2,
        90876,  NA_character_,  NA,
        54321,  'denied',   NA
    )
    
    print(p)
#> # A tibble: 8 x 3
#>      id status    room
#>   <dbl> <chr>    <dbl>
#> 1 12345 approved     5
#> 2 67890 denied      NA
#> 3 13579 approved     7
#> 4 24680 denied      NA
#> 5 80642 <NA>         3
#> 6 97531 <NA>         2
#> 7 90876 <NA>        NA
#> 8 54321 denied      NA
    # I'm trying to conditionally fix the NA values in status. 
    # If status is NA, we need to check the room column. 
    # From there, if room has a non-NA value, status should be "approved", 
    # else status should be changed from NA to "denied".
    
    
    if(is.na(p$status) && is.na(p$room)){
        p$status <- "denied"
    } else if(is.na(p$status) && !is.na(p$room)){
        p$status <- "approved"
    } else {
        p$status <- p$status
    }
    
    p %>%
        mutate(status=case_when(
            !is.na(status)~status,
            !is.na(room)~"approved",
            is.na(room)~"denied"
        ))
#> # A tibble: 8 x 3
#>      id status    room
#>   <dbl> <chr>    <dbl>
#> 1 12345 approved     5
#> 2 67890 denied      NA
#> 3 13579 approved     7
#> 4 24680 denied      NA
#> 5 80642 approved     3
#> 6 97531 approved     2
#> 7 90876 denied      NA
#> 8 54321 denied      NA

Created on 2019-11-11 by the reprex package (v0.3.0)

3 Likes

And for added help, I'm including a solution in Base R.

# A non-tidy solution
    library(tibble)
    p <- tribble(
        ~id,    ~status,    ~room,
        12345,  'approved', 5,
        67890,  'denied',   NA,
        13579,  'approved', 7,
        24680,  'denied',   NA,
        80642,  NA_character_,  3,
        97531,  NA_character_,  2,
        90876,  NA_character_,  NA,
        54321,  'denied',   NA
    )
    
    p$status[is.na(p$status) & !is.na(p$room)] <- 'approved'
    p$status[is.na(p$status) & is.na(p$room)] <- 'denied'
    
    print(p)
#> # A tibble: 8 x 3
#>      id status    room
#>   <dbl> <chr>    <dbl>
#> 1 12345 approved     5
#> 2 67890 denied      NA
#> 3 13579 approved     7
#> 4 24680 denied      NA
#> 5 80642 approved     3
#> 6 97531 approved     2
#> 7 90876 denied      NA
#> 8 54321 denied      NA

Created on 2019-11-11 by the reprex package (v0.3.0)

1 Like

This is great. And doubles as a nice example of how case_when is supposed to work (that one's rough to get until you see it just right). Thanks for everything!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.