What is meaning of first tilde in purrr::map

2019-02-09 05:52发布

问题:

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 = .))

回答1:

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.



标签: r purrr tilde