首页 > 解决方案 > 波浪号运算符可用于构建匿名函数的一般性有哪些?

问题描述

在一些函数 as dplyr::mutate_atorpurrr::map中,似乎可以使用波浪号运算符~来构建匿名函数

例如,可以像链接问题中那样做:map(iris, ~length(unique(.)))

或者还有:mtcars %>% mutate_all(~.*2)

我试着在里面模仿这个sapply,避免sapply(list, function(item) {something_with_item})。我正在写sapply(list, ~ something_with_.),但我得到一个错误

Error in match.fun(FUN) : 
  '~ something_with_.' is not a function, character or symbol

一个可重现的例子:

> sapply(names(mtcars),function(item) mean(mtcars[[item]]))
       mpg        cyl       disp         hp       drat         wt       qsec 
 20.090625   6.187500 230.721875 146.687500   3.596563   3.217250  17.848750 
        vs         am       gear       carb 
  0.437500   0.406250   3.687500   2.812500 
> sapply(names(mtcars),~mean(mtcars[[.]]))
Error in match.fun(FUN) : 
  '~mean(mtcars[[.]])' is not a function, character or symbol

为什么?将这种语法理解为函数只是某些包的行为,例如dplyrpurrrR对于某些特殊情况,base 是否理解?

谢谢!

标签: ranonymous-functiontilde

解决方案


正如 caldwellst 上面所说,tilda~用于创建公式对象,这是一些未评估的代码,可以稍后使用。公式与函数不同,purrr函数与公式一起使用,因为它们在后台调用rlang::as_function(via purrr::as_mapper)。这些*apply函数显然不会这样做,尽管您可以通过在自己修改的*apply函数中调用上述函数之一来模仿这种行为(最好只使用这些map函数,以下只是为了说明这一点):

# Write function with `as_mapper()`.
fapply <- function(x, func) {
    sapply(x, purrr::as_mapper(func))
}

# Now we can use formulae.
fapply(names(mtcars), ~ mean(mtcars[[.]]))

#### OUTPUT ####

       mpg        cyl       disp         hp       drat         wt       qsec         vs         am       gear       carb 
 20.090625   6.187500 230.721875 146.687500   3.596563   3.217250  17.848750   0.437500   0.406250   3.687500   2.812500 

推荐阅读