Search code examples
rdplyrr-haven

if_else with haven_labelled column fails because of wrong class


I have the following data:

dat <- structure(list(value = structure(c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
                                        label = "value: This is my label",
                                        labels = c(`No` = 0, `Yes` = 1),
                                        class = "haven_labelled"),
                      group = structure(c(1, 2, 1, 1, 2, 3, 3, 1, 3, 1, 3, 3, 1, 2, 3, 2, 1, 3, 3, 1),
                                        label = "my group",
                                        labels = c(first = 1, second = 2, third = 3),
                                        class = "haven_labelled")),
                 row.names = c(NA, -20L),
                 class = c("tbl_df", "tbl", "data.frame"),
                 label = "test.sav")

As you can see, the data uses a special class from tidyverse's haven package, so called labelled columns.

Now I want to recode my initial value variable such that:

if group equals 1, value should stay the same, otherwise it should be missing

I was trying the following, but getting an error:

dat_new <- dat %>%
  mutate(value = if_else(group != 1, NA, value))
# Error: `false` must be a logical vector, not a `haven_labelled` object

I got so far as to understand that if_else from dplyr requires the true and false checks in the if_else command to be of same class and since there is no NA equivalent for class labelled (e.g. similar to NA_real_ for doubles), the code probably fails, right?

So, how can I recode my inital variables and preserve the labels?

I know I could change my code above and replace the if_else by R's base version ifelse. However, this deletes all labels and coerces the value column to a numeric one.


Solution

  • You can try dplyr::case_when for cases where group == 1. If no cases are matched, NA is returned:

    dat %>% mutate(value = case_when(group == 1 ~ value))