How to use dplyr to recode all values that are not in a list of values?

Viewed 76

I have a dataframe with a list of names I want to keep, the rest I want to recode to "Other".

namesToKeep = data.frame(
  car = c("Merc 240D", "Cadillac Fleetwood"),
  reason = c("Great car","Me like")
)

selectedCars <- namesToKeep$car
names(selectedCars) <- selectedCars

mtcars %>% mutate(CarName = rownames(mtcars)) %>%
  mutate(
    CarName = recode(CarName, !!!selectedCars, .default = "Other")
  )

The above code works, and demonstrates what I want to do. But I would like to clean it up a bit and not have to calculate a named vector of selected names before hand.

Using base R I can do this by directly mutating the dataframe but I wonder what is the idiomatic dplry way of doing this?

1 Answers

There is a deframe function from tibble which can directly convert the data.frame to a named vector

library(dplyr)
library(tibble)
mtcars %>%
      mutate(CarName = rownames(mtcars),
      CarName = recode(CarName, !!!deframe(namesToKeep), .default = "Other"))

If it is on the same column, use setNames to create the names on the fly

mtcars %>%
     mutate(CarName = rownames(.),
            CarName = recode(CarName, 
    !!! setNames(namesToKeep$car, namesToKeep$car), .default = "Other"))

Or a hacky option is to duplicate the column with indexing and then deframe

mtcars %>%
     mutate(CarName = rownames(.),
            CarName = recode(CarName, 
          !!! deframe(namesToKeep[c(1, 1)]), .default = "Other"))
Related