Search code examples
rdplyracross

mutate with across and .names: "glue cannot interpolate functions into strings" error


I have election results for different candidates by district. The source has the number of votes for each candidate and the total number of votes per district. I'd like to add variables for the percentage of votes that each candidate got in each district.

I have been successful in using mutate with across to replace the vote counts with percentages, but I get an error when trying to use the .names argument to create new variables (i.e I would expect to get new variables, cand1_pct, cand2_pct, ...).

library(tidyverse)
df <- data.frame(district = 1:3,
                 cand1 = c(12, 2, 14),
                 cand2 = c(2, 6, 23),
                 cand3 = c(3, 16, 2),
                 total = c(17, 24, 39))
df %>% 
  mutate(across(2:4, ~ .x/total*100))
#>   district     cand1    cand2     cand3 total
#> 1        1 70.588235 11.76471 17.647059    17
#> 2        2  8.333333 25.00000 66.666667    24
#> 3        3 35.897436 58.97436  5.128205    39
  
df %>% 
  mutate(across(2:4, ~ .x/total*100, .names = "{.col}_pct"))
#> Error: Problem with `mutate()` input `..1`.
#> x glue cannot interpolate functions into strings.
#> * object '.col' is a function.
#> i Input `..1` is `across(2:4, ~.x/total * 100, .names = "{.col}_pct")`.

Created on 2020-08-12 by the reprex package (v0.3.0)

I first thought this was a misunderstanding on my end of how across and .names are supposed to work, but when I use the example from the across vignette I get the same error. I have tried this both on my local machine and RStudio cloud. dplyr version 1.0.1.

library(dplyr)

iris %>%
  group_by(Species) %>%
  summarise(across(starts_with("Sepal"), mean, .names = "mean_{.col}"))
#> Error: Problem with `summarise()` input `..1`.
#> x glue cannot interpolate functions into strings.
#> * object '.col' is a function.
#> i Input `..1` is `across(starts_with("Sepal"), mean, .names = "mean_{.col}")`.
#> i The error occurred in group 1: Species = "setosa".

Created on 2020-08-12 by the reprex package (v0.3.0)


Solution

  • According to ?across, it is not .col, just col

    .names - The default (NULL) is equivalent to "{col}" for the single function case and "{col}_{fn}" for the case where a list is used for .fns.

    library(dplyr)
    df %>% 
       mutate(across(2:4, ~ .x/total*100, .names = "{col}_pct"))
    #  district cand1 cand2 cand3 total cand1_pct cand2_pct cand3_pct
    #1        1    12     2     3    17 70.588235  11.76471 17.647059
    #2        2     2     6    16    24  8.333333  25.00000 66.666667
    #3        3    14    23     2    39 35.897436  58.97436  5.128205