2015-04-13 15 views
9

Sto riscontrando qualche problema con la funzione apply che passa gli argomenti a una funzione quando non è necessaria. Capisco che applicare non sappiano cosa fare con gli argomenti opzionali e basta passarli sulla funzione.Non si applicano tutti gli argomenti facoltativi in ​​applicazione

Ma tant'è, qui è quello che vorrei fare:

Prima di tutto voglio specificare un elenco di funzioni che vorrei utilizzare.

functions <- list(length, sum) 

Quindi vorrei creare una funzione che applica queste funzioni specificate su un set di dati.

myFunc <- function(data, functions) { 
    for (i in 1:length(functions)) print(apply(X=data, MARGIN=2, FUN=functions[[i]])) 
} 

Questo funziona correttamente.

data <- cbind(rnorm(100), rnorm(100)) 
myFunc(data, functions) 

[1] 100 100 
[1] -0.5758939 -5.1311173 

Ma vorrei anche utilizzare argomenti aggiuntivi per alcune funzioni, ad es.

power <- function(x, p) x^p 

Quali non funzionano come voglio. Se modifico myFunc a:

myFunc <- function(data, functions, ...) { 
    for (i in 1:length(functions)) print(apply(X=data, MARGIN=2, FUN=functions[[i]], ...)) 
} 

functions come

functions <- list(length, sum, power) 

e quindi provare la mia funzione ho

myFunc(data, functions, p=2) 

Error in FUN(newX[, i], ...) : 
    2 arguments passed to 'length' which requires 1 

Come posso risolvere questo problema?

Ci scusiamo per il muro di testo. Grazie!

risposta

4

È possibile utilizzare Curry da functional per fissare il parametro che si desidera, inserire la funzione nella lista delle funzioni che si desidera applicare e, infine, iterare questo elenco di funzioni:

library(functional) 

power <- function(x, p) x^p 
funcs = list(length, sum, Curry(power, p=2), Curry(power, p=3)) 
lapply(funcs, function(f) apply(data, 2 , f)) 

Con il vostro codice è possibile utilizzare:

functions <- list(length, sum, Curry(power, p=2)) 
myFunc(data, functions) 
0

Un'opzione è passare i parametri in un elenco con gli argomenti necessari per ciascuna funzione. È possibile aggiungere tali parametri agli altri necessari per apply utilizzando c e quindi utilizzare do.call per chiamare la funzione. Qualcosa come questo. In questo caso, includo anche tutti gli output di un elenco anziché utilizzare print; il tuo utilizzo potrebbe variare.

power <- function(x, p) x^p 
myFunc <- function(data, functions, parameters) { 
    lapply(seq_along(functions), function(i) { 
     p0 <- list(X=data, MARGIN=2, FUN=functions[[i]]) 
     do.call(apply, c(p0, parameters[[i]])) 
    }) 
} 

d <- matrix(1:6, nrow=2) 
functions <- list(length, sum, power) 
parameters <- list(NULL, NULL, p=3) 
myFunc(d, functions, parameters) 
0

È possibile utilizzare il pacchetto lazyeval:

library(lazyeval) 


my_evaluate <- function(data, expressions, ...) { 
    lapply(expressions, function(e) { 
    apply(data, MARGIN=2, FUN=function(x) { 
     lazy_eval(e, c(list(x=x), list(...))) 
    }) 
    }) 
} 

e usarlo in questo modo:

my_expressions <- lazy_dots(sum = sum(x), sumpow = sum(x^p), length_k = length(x)*k) 
data <- cbind(rnorm(100), rnorm(100)) 
my_evaluate(data, my_expressions, p = 2, k = 2) 
1

avrei sostengo utilizzando Curry approccio del colonnello, ma se si vuole posizionare alla base R puoi sempre:

funcs <- list(length, sum, function(x) power(x, 2)) 

che è approssimativamente quello che Curry finisce per fare

Problemi correlati