SIH Tech Tidbits

Useful tips, libraries and tools from the Sydney Informatics Hub team

Using ellipsis (...) and purrr::pmap()


Function with arbitrary arguments using ellipsis (...)

Let's define a function which takes in arbitrary arguments and evaluates an expression on those arguments:

eval_expres <- function(expres, ...){

  #this part gets all the ellipsis (...) arguments, 
  #puts them in a list, and evaluates the rest of the 
  #function from within the environment defined by that list
  with(list(...),

       #actual guts of function
       eval(parse(text = expres))

  )}

Here I chose to explicitly say it needs an argument expres even though it would work with just function(...), because this way, it will throw an error if no expression expres is given.

We can test the function like so:

eval_expres(expres = "2+3")
## [1] 5
eval_expres(expres = "y/x", x = 2, y = pi)
## [1] 1.570796
try(eval_expres())
## Error in parse(text = expres) : 
##   argument "expres" is missing, with no default

Using purrr::pmap() on our function

Let's make an example data frame to use with the eval_expres() function. Each row is two numbers a and b with an expression expres to evaluate.

library(tidyverse)

df = tibble(a = c(1,2,3),
            b = c(5,6,7),
            expres = c("a+b","b^2","sqrt(a)"))

We can then use a function from the purrr::pmap() family to evaluate the function multiple times, once for each row of a data frame.

library(purrr)

pmap_dbl(.l = df, .f = eval_expres)
## [1]  6.000000 36.000000  1.732051