I was looking at this example that uses map
. Here it is:
mtcars %>%
split(.$cyl) %>% # from base R
map(~ lm(mpg ~ wt, data = .))
What is the meaning of the first tilde in map(~ lm...
? That is, how does R interpret the first tilde? (I understand that the second tilde indicates a function...). Another way of asking is, why doesn't the following work?
mtcars %>%
split(.$cyl) %>% # from base R
map(lm(mpg ~ wt, data = .))
As per the map help documentation, map
needs a function but it also accepts a formula, character vector, numeric vector, or list, the latter of which are converted to functions.
The ~
operator in R creates formula. So ~ lm(mpg ~ wt, data = .)
is a formula. Formulas are useful in R because they prevent immediate evaluation of symbols. For example you can define
x <- ~f(a+b)
without f
, a
or b
being defined anywhere. In this case ~ lm(mpg ~ wt, data = .)
is basically a shortcut for function(x) {lm(mpg ~ wt, data = x)}
because map
can change the value of .
in the formula as needed.
Without the tilde, lm(mpg ~ wt, data = .)
is just an expression or call in R that's evaluated immediately. The .
wouldn't be defined at the time that's called and map
can't convert that into a function.
You can turn these formulas into functions outside of the map()
with purrr::as_mapper()
function. For example
myfun <- as_mapper(~lm(mpg ~ wt, data = .))
myfun(mtcars)
# Call:
# lm(formula = mpg ~ wt, data = .)
#
# Coefficients:
# (Intercept) wt
# 37.285 -5.344
myfun
# <lambda>
# function (..., .x = ..1, .y = ..2, . = ..1)
# lm(mpg ~ wt, data = .)
# attr(,"class")
# [1] "rlang_lambda_function"
You can see how the .
becomes the first parameter that's passed to that function.