Подтвердить что ты не робот

Как эффективно частично применить функцию в R?

Предположим, что у меня есть функция в R, которая принимает несколько аргументов, и я хотел бы свести ее к функции меньшего количества аргументов, установив некоторые из аргументов в заранее заданные значения. Я пытаюсь понять, что лучший способ сделать это в R.

Например, предположим, что у меня есть функция

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

Я хотел бы создать или найти функцию partial, которая выполнила бы следующие

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

new_f будет функцией b и d и вернет 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
}

Может ли кто-нибудь сообщить мне более быстрый способ или лучший способ сделать это? Это слишком медленно.

4b9b3361

Ответ 1

В пакете 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

Но с последним вы должны называть аргументы b и d в f(), чтобы избежать ошибки, когда вы хотите оставить a и c как их по умолчанию значения.

Ответ 2

С помощью 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

Ответ 3

У вас также есть Curry из пакета functional:

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