2015-04-13 35 views
9

Mam do czynienia z pewnym problemem z funkcją stosującą przekazywanie argumentów do funkcji, gdy nie jest to konieczne. Rozumiem, że zastosowanie nie wiem, co zrobić z opcjonalnymi argumentami i po prostu przekazać je do funkcji.Nie przekazuję wszystkich opcjonalnych argumentów w zastosowaniu

Ale tak czy inaczej, tutaj jest to, co chciałbym zrobić:

Najpierw chcę określić listę funkcji, które chciałbym użyć.

functions <- list(length, sum) 

Następnie chciałbym utworzyć funkcję, które znajdują zastosowanie tych określonych funkcji na zbiorze danych.

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

To działa dobrze.

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

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

Chciałbym jednak użyć dodatkowych argumentów dla niektórych funkcji, np.

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

Które nie działają tak, jak chcę. Gdybym modyfikować myFunc do:

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

functions jak

functions <- list(length, sum, power) 

a następnie spróbować swoich funkcji otrzymuję

myFunc(data, functions, p=2) 

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

Jak mogę rozwiązać ten problem?

Przepraszamy za ścianę tekstu. Dziękuję Ci!

Odpowiedz

4

Można użyć Curry od functional naprawić parametr, który chcesz umieścić funkcję w liście funkcji, którą chcesz zastosować i wreszcie iteracyjne nad tą listą funkcji:

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)) 

z kodem możesz użyj:

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

Jedną z opcji jest przekazanie parametrów na liście z argumentami potrzebnymi dla każdej funkcji. Możesz dodać te parametry do innych wymaganych dla apply przy użyciu c, a następnie użyć do.call, aby wywołać funkcję. Coś takiego. Zawijam również wszystkie dane wyjściowe na liście zamiast używać print; twoje użycie może się różnić.

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

Można użyć pakietu 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(...))) 
    }) 
    }) 
} 

i używać go tak:

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

będę zwolennikiem korzystania Curry podejście pułkownika, ale jeśli chcesz, aby trzymać się zasady, R zawsze możesz:

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

co jest mniej więcej tym, co Curry kończy na zrobieniu

Powiązane problemy