knitr::opts_chunk$set( eval = TRUE, collapse = TRUE, comment = "#>" )
suppressWarnings({ library(rlang) library(lobstr) library(tibble) library(dplyr, warn.conflicts = FALSE) library(palmerpenguins) })
These notes were made whilst reading the metaprogramming chapters 17 - 20 in Hadley Wickham's Advanced R book.
Additional resources
# symbol assigned with a constant in the global environment species_name <- "Gentoo" gender <- "male" # symbol assigned with a constant in a tibble in the global environment data_tibble <- tibble(species_name = "Chinstrap", gender = "female") # create a new data environment penguin_environment <- env() # symbol assigned with a constant in the data environment assign("species_name", "Adelie", envir = penguin_environment) assign("gender", "unknown", envir = penguin_environment)
# view expression as abstract syntax tree ast(function_name <- function(parameter = "Gentoo"){ return(parameter_value) })
Ability to both capture an expression without evaluation using quotation and selectively evaluating part of this quoted expression using unquotation
# parse constant string as an expression parse_expr('species_name <- "Gentoo"') # parse symbol name as an expression expr(species_name) # base equivalent = quote(species_name) # parse multiple symbols names as a list of expressions exprs(species_name, gender) # base equivalent = alist(species_name, gender) # parse symbol's assigned constant as an expression enexpr(species_name) # base equivalent = substitute(species_name) # parse multiple symbol's assigned constants as an expression enexprs(species_name, gender) # parse multiple constant arguments in function passed using ... data <- function(...) { enexprs(...) # base equivalent = as.list(substitute(...())) } data(species_name = "Gentoo", gender = "male") # quosure - capture symbol name as expression along with its environment quo(species_name) # quosures - capture list of symbol names as expression along with its environment quos(species_name, gender) # quosure - capture symbol's assigned constant as an expression along with its environment enquo(species_name) # quosures - capture a list of symbol's assigned constants as expressions along its their environment enquos(species_name, gender)
# convert a string constant into a symbol sym("species_name") # parse symbols assigned symbol as an expression ensym(species_name) # parse multiple symbols assigned symbols as an expression ensyms(species_name, gender) # parse multiple symbol arguments in function passed using ... data <- function(...) { ensyms(...) } data(species_name = Gentoo, gender = male)
# evaluate part of the expression using the unquote operator !! expr(!!expr(species_name) <- !!enexpr(species_name)) expr(!!sym("gender") <- !!enexpr(gender)) # evaluate multiple symbols names stored as a list of expressions expr(f(!!!exprs(species_name, gender)))
# convert a symbol into a string constant expr_text(expr(species_name)) # base equivalent = deparse(quote(species_name))
# evaluate a symbol expression assigned to a constant within a specified environment eval(expr = expr(species_name)) eval(expr = expr(species_name), envir = penguin_environment)
eval_tidy(expr = enquo(species_name))
eval_tidy(expr = expr(species_name), data = data_tibble)
get_maximum_value <- function(data, category, variable) { # quosure containing parameter's value as an expression and its environment category <- enquo(category) # species variable <- enquo(variable) # body_mass_g # evaluate quosure using the unquote operator data |> group_by(!!category) |> summarise(maximum = max(!!variable, na.rm = TRUE)) } penguins |> get_maximum_value(category = species, variable = body_mass_g)
# {{ }} is a short hand replacement for !!(enquo(x)) get_maximum_value <- function(data, category, variable) { # create and unquote quosure containing parameter's value as an expression and its environment using {{ }} data |> group_by({{category}}) |> summarise(maximum = max({{variable}}, na.rm = TRUE)) } penguins |> get_maximum_value(category = species, variable = body_mass_g)
get_maximum_value <- function(data, category, ...) { # create and unquote multiple quosures using ... data |> group_by({{category}}) |> summarise(...) } penguins |> get_maximum_value(category = species, average = mean(body_mass_g, na.rm = TRUE), maximum = max(body_mass_g, na.rm = TRUE))
get_maximum_value <- function(data, category, variable) { # use := to quote and unquote on left hand side of = data |> group_by({{category}}) |> summarise("{{category}}_maximum" := max({{variable}}, na.rm = TRUE)) } penguins |> get_maximum_value(category = species, variable = body_mass_g)
get_maximum_value <- function(data, category, variable, unit) { # use {} to add string and := to quote and unquote on left hand side of = data |> group_by({{category}}) |> summarise("maximum_{unit}" := max({{variable}}, na.rm = TRUE)) } penguins |> get_maximum_value(category = species, variable = body_mass_g, unit = "gram")
# .data[[ ]] pronoun is used when parameter values are strings, to distinguish from using environment constant values identified by the .env pronoun get_maximum_value <- function(data, category, variable) { # create and unquote quosure containing parameter's value as an expression and its environment using {{ }} data |> group_by(.data[[category]]) |> summarise(maximum = max(.data[[variable]], na.rm = TRUE)) } penguins |> get_maximum_value(category = "species", variable = "body_mass_g")
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.