Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Can you use a parameter in a function name with tidy eval/NSE/metaprogramming?

I am writing a function that makes ggplots with given data, and I am interested in setting a parameter that can call the different scales::label_* functions to change the outputs. For example, I want to be able to call create_pie_chart(starwars, fill = gender, label = "percent") and have the labels appear using scales::label_percent or create_pie_chart(starwars, fill = gender, label = "date") and have the labels use scales::label_date.

I know I could just use some if else statements, but I’m curious if there is a tidy eval or NSE way to do this? Maybe using substitute or {{}}?

Here is an example where I tried to use glue to create the function name — it does not work:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

library(dplyr)

create_pie_chart <- function(data,
                             fill,
                             label = "percent") {

    data_counts <- data %>%
      dplyr::summarize(num = dplyr::n(), .by = {{ fill }}) %>%
      dplyr::mutate(prop = num/sum(num))
    
    label_function <- glue::glue("scales::label_", label)
    
    plot <- data_counts %>%
      ggplot2::ggplot(ggplot2::aes(x="", y = prop, fill = {{ fill }})) +
      ggplot2::geom_bar(width = 1, stat = "identity") +
      ggplot2::coord_polar("y", start = 0) + 
      ggplot2::geom_label(
        # This is the line where I would like to use tidy eval
        # to call `scales::label_*` with my `label` parameter
        ggplot2::aes(label = label_function()(prop)),
        position = ggplot2::position_stack(vjust = 0.5)
      ) +
      ggplot2::theme_void()
    
    plot
}

data("starwars")

create_pie_chart(starwars, fill = gender, label = "percent")

I have also tried match.fun/get(..., mode = function) as described in this question, but I get an error stating:

Error in get(as.character(FUN), mode = "function", envir = envir) :
object 'scales::label_percent' of mode 'function' was not found

>Solution :

No need for tidyeval. You can use getExportedValue to find a name inside a namespace; so to find scales::label_X, you could use getExportedValue("scales", "label_X"):

label_function <- getExportedValue("scales", glue::glue("label_{label}"))

For non-qualified names (i.e. if you didn’t have scales:: in front of it), you can instead use get(name, mode = "function").

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading