Search code examples
rdplyrassignment-operator

Is there a stable (non-deprecated) dplyr way of adding multiple columns based on a vector of names?


Let's assume I have a simple data.frame:

> d <- data.frame(A=1, B=2)

Now I want to add 3 columns, {X, Y, Z} stored in a vector to it. Let's skip the reasons for, and focus on the solution, please.

In the base R I can do it trivially:

> columns_to_add <- c("X", "Y", "Z")
> d[,columns_to_add] <- NA
> d
  A B  X  Y  Z
1 1 2 NA NA NA

But how to do this with the dplyr? I understand there must be a combination using the mutate (remembering, that the mutate_at, mutate_all will be deprecated one day), the ":=" assignment operator and the {{}} or triple-bang operator !!!rlang::syms()?

Let's have:

> single_name <- c("x")
> multip_name <- c("x", "y", "z")

For a single name it works:

> d %>% mutate(!!sym(single_name) := NA)
  A B  x
1 1 2 NA
> d %>% mutate({{single_name}} := NA)
  A B  x
1 1 2 NA

But for more than 1 name it doesn't work:

> d %>% mutate({{multip_name}} := NA)
Error: The LHS of `:=` must be a string or a symbol
Run `rlang::last_error()` to see where the error occurred.

> d %>% mutate(!!!syms(multip_name) := NA)
Error: The LHS of `:=` can't be spliced with `!!!`
Run `rlang::last_error()` to see where the error occurred.

It doesn't have to be "mutate", please propose anything that:

  • comes from the tidyverse

  • doesn't rely on any "superseded", "deprecated" stuff.


Solution

  • One approach could be:

    d %>%
     add_column(!!!setNames(rep(NA, length(multip_name)), multip_name))
    
      A B  x  y  z
    1 1 2 NA NA NA