3

I can use the vars() wrapper inside mutate_at to perform a mutation on variables whose names are in a character vector:

library(tidyverse)

varnames <- c("mpg", "am")

mtcars.mod <- mtcars %>%
  mutate_at(vars(varnames),
            funs(as.factor(.)))

is.factor(mtcars.mod$mpg)
#> [1] TRUE

But what if I want to add a predicate/condition on those variables, like I could do with mutate_if? In other words, I want to perform a mutation on variables which (1) are included in varnames and (2) satisfy a predicate, such as !is.factor()

My attempt, which fails:

mtcars.mod <- mtcars %>%
  mutate_if(~ (names(.) %in% varnames & !is.factor(.)),
            funs(as.factor(.)))
#> Error in selected[[i]] <- .p(.tbl[[vars[[i]]]], ...): replacement has length zero

I suspect that names(.) might be returning NULL here.

lost
  • 1,483
  • 1
  • 11
  • 19
  • 2
    this works, `mtcars.mod <- mtcars %>% mutate_if((names(.) %in% varnames & !is.factor(.)), funs(as.factor(.)))` , `is.factor(mtcars.mod$mpg) #[1] TRUE` – Ronak Shah Dec 05 '18 at 03:50
  • Hmm yeah, it looks like it does. It's not clear to me when the `~` is required. For example, this fails but works if `~` is added: `mtcars.mod <- mtcars %>% mutate_if((is.numeric(.) & !is.factor(.)), funs(as.factor(.)))` – lost Dec 05 '18 at 04:13

0 Answers0