【问题标题】:How to efficiently partially apply a function in R?如何有效地部分应用 R 中的函数?
【发布时间】:2015-11-17 09:08:23
【问题描述】:

假设我在 R 中有一个接受多个参数的函数,并且我想通过将一些参数设置为预先指定的值来将其简化为一个参数更少的函数。我试图弄清楚在 R 中最好的方法是什么。

例如,假设我有一个函数

f <- function(a,b,c,d){a+b+c+d}

我想创建或找到一个可以执行以下操作的函数部分

partial <- function(f, ...){
#fill in code here
}
new_f <- partial(f, a=1, c= 2)

new_f 将是 bd 的函数,并将返回 1+b+2+d

在python中我会这样做

from functools import partial

def f(a,b,c,d):
    return a+b+c+d

new_f = partial(f, a=1, c= 2)

我实际上是在重复这样做,所以我需要尽可能高效。谁能指出最有效的方法来做到这一点?现在我能做的最好的就是

partial <- function(f, ...){
    z <- list(...)
    formals(f) [names(z)] <- z
    f
}

谁能告诉我更快的方法或最好的方法?这简直太慢了。

【问题讨论】:

  • 您可以使用formals(f)[c("a", "c")] &lt;- list(1, 3) 更改其形式参数或使用pryr::partial(f, a = 1, c = 2)
  • 谢谢。如果您作为答案发布,我会接受。 pryr 的部分是我想要的。

标签: r function partial-application


【解决方案1】:

您可以使用do.call 编写自己的代码,而无需编写太多代码:

partial <- function(f, ...) {
  l <- list(...)
  function(...) {
    do.call(f, c(l, list(...)))
  }
}

基本上partial 返回一个存储f 以及最初提供的参数(存储在列表l 中)的函数。调用此函数时,它会同时传递l 中的参数和任何其他参数。它在行动中:

f <- function(a, b, c, d) a+b+c+d
p <- partial(f, a=2, c=3)
p(b=0, d=1)
# [1] 6

【讨论】:

  • 对于列表作为简单参数,使用此代码partial_list&lt;-function(f, L){ function(...){ do.call(f, c(L, list(...))) } }
【解决方案2】:

pryr 包中有函数可以处理这个问题,即partial()

f <- function(a, b, c, d) a + b + c + d 
pryr::partial(f, a = 1, c = 2)
# function (...) 
# f(a = 1, c = 2, ...)

所以你可以这样使用它 -

new_fun <- pryr::partial(f, a = 1, c = 2)
new_fun(b = 2, d = 5)
# [1] 10
## or if you are daring ...
new_fun(2, 5)
# [1] 10

你也可以简单地改变f()的形式参数

f <- function(a, b, c, d) a + b + c + d 
formals(f)[c("a", "c")] <- list(1, 2)
f
# function (a = 1, b, c = 2, d) 
# a + b + c + d
f(b = 2, d = 5)
# [1] 10

但对于后者,您必须f() 中命名bd 参数以避免在您想将ac 保留为默认值时出错价值观。

【讨论】:

  • 好像purrr包里面还有一个partial;虽然不确定差异。不过,这帮助我找到了正确的位置,所以 +1!
【解决方案3】:

你也有来自包functionalCurry

library(functional)

f <- function(a, b, c, d) a+b+c+d
ff = Curry(f, a=2, c=10)

ff(1,5)
#[1] 18

ff(b=1,d=5)
#[1] 18

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多