2
votes

Consider these factor objects:

x <- factor(c(1,2,2,4,5), 1:5, labels = c('Ja', 'Nein', '', 'Weiß nicht', 'Keine Antwort'))
y <- factor(c(1:5), 1:5, labels = c('Ja', 'Nein', '', 'Weiß nicht', 'Keine Antwort'))

> table(x)
x
           Ja          Nein                  Weiß nicht Keine Antwort 
            1             2             0             1             1 

> table(y)
y
           Ja          Nein                  Weiß nicht Keine Antwort 
            1             1             1             1             1 

I'm trying to use dplyr::recode to recode various variables. I can't get the function to recode an empty string level to NA and to drop the specific factor level.

Using

dplyr::recode(x,
              "Weiß nicht" = NA_character_,
              "Weiß nicht " = NA_character_,
              "Keine Antwort" = NA_character_,
              "Keine Antwort " = NA_character_,
              "k.A." = NA_character_,
              "Keine Angabe" = NA_character_,
              "0" = NA_character_,
              "" = NA_character_)

will result in an error message (Error: attempt to use zero-length variable name). Using

z <- dplyr::recode(na_if(x, ""),
              "Weiß nicht" = NA_character_,
              "Weiß nicht " = NA_character_,
              "Keine Antwort" = NA_character_,
              "Keine Antwort " = NA_character_,
              "k.A." = NA_character_,
              "Keine Angabe" = NA_character_,
              "0" = NA_character_)

as described in Recode character vector with some empty strings does not get rid of the empty string level:

> table(z)
z
  Ja Nein      
   1    2    0 
> levels(z)
[1] "Ja"   "Nein" "" 

Additionally, I can't simply use droplevels because I want to use the function on variables which may have empty categories I need to retain.

A solution would need to provide to things:

  1. Recode any occurence of "" to NA.
  2. Drop level "" from factor variable, even when it is unused (as in x), without dropping every unused level.
1

1 Answers

1
votes

We assign the levels that are "" to NA before the recode

levels(x)[levels(x)==""] <- NA_character_
y <- dplyr::recode(x,
          "Weiß nicht" = NA_character_,
          "Weiß nicht " = NA_character_,
          "Keine Antwort" = NA_character_,
          "Keine Antwort " = NA_character_,
          "k.A." = NA_character_,
          "Keine Angabe" = NA_character_,
          "0" = NA_character_))

levels(y)
#[1] "Ja"   "Nein"

table(y)
y
#  Ja Nein 
#  23 2728 

Using the smaller dataset

x2 <- x1[1:7]
levels(x2)[levels(x2)==""] <- NA_character_
x2
#[1] b    b    e    d    d    <NA> b   
#Levels: a b c d e


table(dplyr::recode(x2, "b" = NA_character_))

#  a c d e 
#  0 0 2 1  

Here 'c' and 'a' are unused levels, while 'b' is changed to NA as well as "" to NA

data

set.seed(24)
x1 <- factor(sample(c(letters[1:5], ""), 20, replace = TRUE))
x2 <- x1[1:7]