rfunctionpivotcurly-braces

Using Curly-Curly {{}} in the Argument names_glue of pivot_wider() in a R Function


Hello everyone and thank you in advance for your responses.

Per default, tidyr::pivot_wider() in R creates the new column names with the values from "names_from" in the suffix. This can be changed by including a "names_glue = {var1}_{var2}"-argument (as seen here: R: Changing column names in pivot_wider() -- suffix to prefix). However, since I am trying to pivot_wider in a function and I cannot figure out how I need to apply this argument to a curly-curly-variable (see example below).

I need to rename the columns that way so that I can reorder the columns alphabetically later, so that the column with the absolute number and percentage are displayed for Party A first, then for Party B, etc. (instead of all the absolute numbers first and then all the percentages second). Can someone help me?

Example: I have a dataset with political candidates, their party alliance and their sociodemographic information. How many men/women are there overall and per party (in absolute and relative terms)?

# Create example data frame:
Datensatz <- data.frame(Kandidat= c("Candidate A", "Candidate B", "Candidate C", "Candidate D"),
                 Partei = c("Party A", "Party B", "Party A", "Party C"),
                 Geschlecht = c("Male", "Female", "Female", "Female"))
Datensatz

# My current function code:
stats_sociodem <- function(data, var, parties){

  # Create tables for statistics overall
  sv_stats_all <- data %>%
    group_by({{var}}) %>%
    summarise(all_n = n()) %>%
    mutate(all_per = prop.table(all_n) * 100)

  # Create table for statistics grouped by parties
  sv_stats <- data %>%
    group_by({{var}}, {{parties}}) %>%
    summarise(n = n()) %>%
    group_by({{parties}}) %>%
    mutate(per = prop.table(n) * 100) %>%
    pivot_wider(names_from = {{parties}},
                values_from = c("n", "per"),
                names_glue = "{{{parties}}}_{.value}"
                ) %>%
    select({{var}}, sort(names(.)))

  # Join
  var_name <- deparse(substitute(var))
  sv_stats_final <- left_join(sv_stats, sv_stats_all, by=var_name)
sv_stats_final
}

# Application example for gender statistics:
stats_sociodem(Datensatz, Geschlecht, Partei)

Maybe I could use regular expressions, but not sure.


Solution

  • You were already hinting to a solution when you use deparse(substitute()) further below.

    library(tidyverse)
    
    # My current function code:
    stats_sociodem <- function(data, var, parties){
      
      # Create tables for statistics overall
      sv_stats_all <- data %>%
        group_by({{var}}) %>%
        summarise(all_n = n()) %>%
        mutate(all_per = prop.table(all_n) * 100)
      
      parties_name <- deparse(substitute(parties)) # New
      
      # Create table for statistics grouped by parties
      sv_stats <- data %>%
        group_by({{var}}, {{parties}}) %>%
        summarise(n = n()) %>%
        group_by({{parties}}) %>%
        mutate(per = prop.table(n) * 100) %>%
        pivot_wider(names_from = {{parties}},
                    values_from = c("n", "per"),
                    names_glue = paste0("{", parties_name, "}_{.value}") # New
        ) %>%
        select({{var}}, sort(names(.)))
      
      # Join
      var_name <- deparse(substitute(var))
      sv_stats_final <- left_join(sv_stats, sv_stats_all, by=var_name)
      sv_stats_final
    }
    
    # Application example for gender statistics:
    stats_sociodem(Datensatz, Geschlecht, Partei)