library(purrr)Using the purrr function shortcuts in your own custom functions
purrr::map() more deeply along the way
Functionals basics
Functionals are defined as functions that take a function as input and return a vector as output. The simplest non-base R way to do this is by using a purrr::map_*() function. These functions simply apply the user specified function to each element in the input vector and returns an object with the same number of elements as the input.
square <- function(x) x ^ 2
map_dbl(1:3, square)[1] 1 4 9
We can simplify this by making use of anyonymous functions and shortcuts. First we can define our function inside of map_dbl and since we don’t have to bind it to a name it is considered an anonymous function:
map_dbl(1:3, function(x) x ^ 2)[1] 1 4 9
Next we can use a special purrr shortcut to simplify this code even further
map_dbl(1:3, ~ .x ^ 2)[1] 1 4 9
Technically it would be most correct to write
map_dbl(1:3, ~ . ^ 2)[1] 1 4 9
since the convention with these formula objects is to use
.for a single argument function.xand.yfor a two argument function..1,..2,..3, etc for functions with more arguments
but sometimes it’s nice to still see the x in the formula.
Either way, this code is wonderfully clean and concise and it sure would be nice if we could write our own functions that use the same syntax. And the good news is that we can! The solution only relies on the use of the function purrr::as_mapper() which can convert a formula object into a function.
To demonstrate that functionality I’ll show a small toy example:
func_formula <- ~ .x ^ 2
func <- as_mapper(func_formula)
func(2)[1] 4
And actually, under the hood, purrr::map() is first applying this as_mapper() function to the user supplied function which explains why we can supply functions to map() in so many different ways.
purrr::mapfunction (.x, .f, ...)
{
.f <- as_mapper(.f, ...)
.Call(map_impl, environment(), ".x", ".f", "list")
}
<bytecode: 0x55edc063a788>
<environment: namespace:purrr>
So with this knowledge under our belt, we can write a custom function of our own that is able to use that clean and concise syntax that map() allows.
Although this is certainly not a very useful function, it shows a very bare bones example of how you can write your own functions to use the purrr shortcut syntax!
all_met <- function(.x, .f, ...){
.f <- as_mapper(.f, ...)
for (i in .x) {
if(!.f(i)) return(F)
}
return(T)
}
all_met(2:5, ~ .x > 1)[1] TRUE
all_met(1:5, ~ .x > 1)[1] FALSE