我可以定义和使用匿名函数并像这样调用它
x <- 1:3
sapply(x, function(x) x)
有时候,我觉得使用这样的函数太冗长了。还有另一种定义匿名函数的方法吗?
在purrr
包中,可以定义这样的匿名函数
map(x, ~.x)
但这仅在purrr
上下文中有效。
答案 0 :(得分:7)
您能做到多详细?您需要某种指示符,以表明这是一个函数,以某种方式表示自变量,以某种方式表示计算。使其“冗长”的唯一原因是“功能”有八个字母。如果您不希望这样做,请在应用中外部定义函数,然后获得sapply(x, foo)
,它简洁明了且易于理解,并且无需借助外部依赖项(purrrr)或非标准评估。
答案 1 :(得分:7)
1)gsubfn :: fn gsubfn package支持用于定义函数的公式表示法,与问题中提到的purrr不同,该方法仅适用于purrr函数,几乎可与任何函数兼容功能。
如果将匿名函数传递给另一个函数,则在示例中,匿名函数传递给sapply
,然后在sapply
前面加上fn$
并使用args形式的公式表示法〜身体。如果缺少args,则假定主体中的自由变量是在主体中遇到的顺序的参数,因此在下面的第一个示例z
中,将其视为单个参数。
library(gsubfn)
x <- 1:3
fn$sapply(x, ~ z)
## [1] 1 2 3
# same - specify arg
fn$sapply(x, z ~ z)
## [1] 1 2 3
# same - can use any variable name we like
fn$sapply(x, ~ x)
## [1] 1 2 3
# same
sapply(x, function(z) z)
## [1] 1 2 3
匿名函数可以具有任意数量的参数。以下是相同的:
fn$sapply(x, ~ u + 2 * v, v = 10)
## [1] 21 22 23
# same
fn$sapply(x, u + v ~ u + 2 * v, v = 10)
## [1] 21 22 23
# same
sapply(x, function(u, v) u + 2 * v, v = 10)
## [1] 21 22 23
2)magrittr
magrittr package支持用于定义单个参数函数的管道符号。参数必须为点。
library(magrittr)
x <- 1:3
sapply(x, . %>% {.})
## [1] 1 2 3
# same
sapply(x, function(x) x)
## [1] 1 2 3
# same
x %>% sapply(. %>% {.})
## [1] 1 2 3
3)lambda.r lambda.r package允许使用%as%
定义以命名的函数。在这里,我们定义了一个名为fun
的函数。
library(lambda.r)
x <- 1:3
fun(x) %as% x
sapply(x, fun)
## [1] 1 2 3
# same
fun <- function(x) x
sapply(x, fun)
## [1] 1 2 3
答案 2 :(得分:2)
'wrapr'软件包提供了几种缩写匿名函数的方法。在LINUX平台上(允许lambda字符成为可用于命名符号的“字母”取决于OS和语言环境),您可以执行以下操作:
library(wrapr)
λ <- lambda
sapply(1:10,λ(x,x^2))
#[1] 1 4 9 16 25 36 49 64 81 100
λ(x,y,x*y)(6,7)
#[1] 42
答案 3 :(得分:2)
L
函数允许非常紧凑的函数定义,它从您提供给它的表达式中猜测函数的参数,对于简单的调用来说效果很好。<!ELEMENT I ((P|L)+)>
使用pryr::f
,它本身称为purrr
,因此您也可以调用它们,尽管它并不那么冗长。示例:
purrr::as_mapper
rlang::as_function
您可以将其分配给简短变量以使用紧凑语法:
aggregate(. ~ Species, iris, pryr::f(mean(range(.))))
# Species Sepal.Length Sepal.Width Petal.Length Petal.Width
# 1 setosa 5.05 3.35 1.45 0.35
# 2 versicolor 5.95 2.70 4.05 1.40
# 3 virginica 6.40 3.00 5.70 1.95
aggregate(. ~ Species, iris, rlang::as_function(~mean(range(.))))
# Species Sepal.Length Sepal.Width Petal.Length Petal.Width
# 1 setosa 5.05 3.35 1.45 0.35
# 2 versicolor 5.95 2.70 4.05 1.40
# 3 virginica 6.40 3.00 5.70 1.95
.. <- rlang::as_function
aggregate(. ~ Species, iris, ..(~mean(range(.))))
其他功能,例如aggregate(. ~ Species, iris, purrr::as_mapper(~mean(range(.))))
# Species Sepal.Length Sepal.Width Petal.Length Petal.Width
# 1 setosa 5.05 3.35 1.45 0.35
# 2 versicolor 5.95 2.70 4.05 1.40
# 3 virginica 6.40 3.00 5.70 1.95
,# devtools::install_github("moodymudskipper/lambda")
library(lambda)
attach_lambda()
aggregate(. ~ Species, iris, ~mean(range(.)))
# Species Sepal.Length Sepal.Width Petal.Length Petal.Width
# 1 setosa 5.05 3.35 1.45 0.35
# 2 versicolor 5.95 2.70 4.05 1.40
# 3 virginica 6.40 3.00 5.70 1.95
,base::Negate
,base::vectorize
...有时可以帮助使代码更紧凑。
答案 4 :(得分:1)
我敢肯定,任何明智的R程序员在接下来的工作中都应认真对待,但似乎有点乐趣,这似乎行得通,并且消除了必须调用6个字母长的函数的麻烦
s=function(x,f)
{
eval(parse(text = paste('y <- function(x)',deparse(substitute(f)),collapse='')))
sapply(x,y)
}
所以现在使用s
代替了sapply
。
s(1:3,x*2)
## [1] 2 4 6
x必须用作该函数的单个参数,这可能像地狱一样容易出错。