2015-08-24 9 views
23

Supponiamo di avere una funzione in R che richiede più argomenti e vorrei ridurla a una funzione di un numero inferiore di argomenti impostando alcuni degli argomenti su valori predefiniti. Sto cercando di capire che cosa è il modo migliore per farlo è in R.Come applicare parzialmente una funzione in modo efficiente in R?

Per esempio, supponiamo di avere una funzione

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

Mi piacerebbe creare o trovare una funzione parziale che farebbe il seguente

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

new_f sarebbe una funzione di b e d e ritornerebbe 1+b+2+d

in Python che avrei fatto

from functools import partial 

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

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

realtà sto facendo questo più volte e quindi ho bisogno per questo di essere il più efficiente possibile. Qualcuno può indicarmi il modo più efficiente per farlo? In questo momento il meglio che posso fare è

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

Qualcuno può farmi sapere un modo più veloce o il modo migliore per farlo? Questo è semplicemente troppo lento.

+1

Si potrebbe o modificare i suoi argomenti formali con 'formali (f) [c ("a", "c")] <- elenco (1, 3) o usa 'pryr :: partial (f, a = 1, c = 2)' –

+0

grazie. se pubblichi come risposta accetterò. il parziale di pryr era ciò che volevo. – k13

risposta

18

Ci sono funzioni nel pacchetto pryr in grado di gestire questo, vale a dire partial()

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

modo da poterlo utilizzare in questo modo -

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 

È potrebbe anche semplicemente cambiare gli argomenti formali di f() con

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 

Ma con quest'ultimo, si must nome le b e d argomenti a f() per evitare un errore quando si vuole lasciare a e c come i loro valori di default.

+1

Sembra che ci sia anche un 'partial' nel pacchetto' purrr'; non sono sicuro delle differenze però.Questo mi ha aiutato a farmi trovare il posto giusto, quindi +1! – dwanderson

22

Si potrebbe rotolare il proprio, senza troppo codifica utilizzando do.call:

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

Fondamentalmente partial restituisce una funzione che memorizza f così come gli argomenti originariamente previste (memorizzati nella lista l). Quando viene chiamata questa funzione, vengono passati entrambi gli argomenti in l e qualsiasi argomento aggiuntivo. Eccolo in azione:

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

Hai anche Curry dal pacchetto 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 
Problemi correlati