Passing variables into the names_glue parameter of tidyr::pivot_wider

6.6k views Asked by At

Here's some silly data that we pivot wider, using two names:

library(tidyr)

df <- data.frame(
    food = c('banana','banana','banana','banana','cheese','cheese','cheese','cheese'),
    binary = c(rep(c('yes','no'), 4)),
    car = c('toyota','subaru','mazda','skoda','toyota','subaru','mazda','skoda'),
    fun = c(2,4,3,6,2,4,2,3))

df %>%
    pivot_wider(
        id_cols = food,
        names_from = c(car, binary),
        values_from = fun)

If we want to change the format of the new variable names, e.g., from toyota_yes to yes_toyota, we use the names_glue argument:

df %>%
    pivot_wider(
        id_cols = food,
        names_from = c(car, binary),
        names_glue = "{binary}_{car}",
        values_from = fun)

The issue I'm facing is finding the correct syntax to pass variable names to the names_glue parameter. It's easy to pass variables to names_from, e.g.:

var1 <- 'car'
var2 <- 'binary'
df %>%
    pivot_wider(
        id_cols = food,
        names_from = c(var1, var2),
        values_from = fun)

But we can't directly do that with names_glue:

df %>%
    pivot_wider(
        id_cols = food,
        names_from = c(var1, var2),
        names_glue = "{var1}_{var2}",
        values_from = fun)

Error: Column names car_binary, car_binary, and car_binary must not be duplicated.

Presumably it's evaluating the variable and just passing the resulting string (i.e., 'car' or 'binary') into the glue function. I have played around with some things I would normally use for tidy evaluation (!!sym(...), etc.) but haven't got anything to work. Desired output is the following, using variables for the names_glue parameter:

# A tibble: 2 x 5
  food   yes_toyota no_subaru yes_mazda no_skoda
  <fct>       <dbl>     <dbl>     <dbl>    <dbl>
1 banana          2         4         3        6
2 cheese          2         4         2        3

Here is the commit that added the names_glue parameter to pivot_wider -- although I can't really figure out how to troubleshoot with this.

3

There are 3 answers

0
Ronak Shah On BEST ANSWER

You can use sprtinf/paste0 to construct the string :

library(tidyr)
df %>%
  pivot_wider(
    id_cols = food,
    names_from = c(var1, var2),
    names_glue = sprintf('{%s}_{%s}', var2, var1),
    values_from = fun)

#  food   yes_toyota no_subaru yes_mazda no_skoda
#  <chr>       <dbl>     <dbl>     <dbl>    <dbl>
#1 banana          2         4         3        6
#2 cheese          2         4         2        3
0
akrun On

We can create the pattern with glue

library(dplyr)
library(tidyr)
df %>%
     pivot_wider(
         id_cols = food,
         names_from = c(var1, var2),
         names_glue = glue::glue("{[var1]}_{[var2]}", .open = '[', .close = ']'),
         values_from = fun)
# A tibble: 2 x 5
#  food   toyota_yes subaru_no mazda_yes skoda_no
#  <chr>       <dbl>     <dbl>     <dbl>    <dbl>
#1 banana          2         4         3        6
#2 cheese          2         4         2        3
0
Tom Wagstaff On

I don't know if this was available at the time of posting, but the tidyr documentation suggests you can just pass this "{var1}_{var2}" syntax directly to names_glue these days (without having to define any variables outside the dataframe either) and it seems to be working for me!