2011-02-10 10 views
8

To jest pytanie dotyczące kodowania w R.R: określanie łańcucha jako argumentu funkcji, która wywołuje inną funkcję

Podany przeze mnie przykład jest dydaktyczny. Załóżmy, że mam funkcje o nazwie "func1" i "func2", gdzie każdy bierze dwa argumenty (powiedzmy skalary). Chcę określić inną funkcję "applyfunction", która ma trzy argumenty: ostatni numer funkcji do użycia ("1" lub "2") i dwa argumenty dla funkcji. Na przykład, chcę zrobić coś takiego (co oczywiście nie działa):

applyfunction(1,2,3) gdzie skutecznie uruchomić func1(2,3) i

applyfunction(2,9,43) gdzie skutecznie uruchomić func2(9,43).

Wszelkie pomysły?

Best, DB

Odpowiedz

7

Możecie zajrzeć do do.call(), która wywołuje funkcję z argumentami dostarczonych w postaci listy. Nie jest trudno napisać opakowanie wokół tego, co robi dokładnie to, co chcesz.

function1=function(a,b)a+b 
function2=function(a,b,c)a+b+c 

do.call("function1",list(1,2)) 
do.call("function2",list(1,2,3)) 

EDIT: Owijka byłoby:

applyfunction=function(fun,...)do.call(fun,list(...)) 

applyfunction("function1",1,2) 
applyfunction("function2",1,2,3) 
6

Oto kolejna alternatywa. Możesz dodać więcej funkcji do listy switch.

func1 <- function(a, b) a + b 
func2 <- function(a, b) a - b 
applyfunction <- function(FUN, arg1, arg2) { 
    appFun <- switch(FUN, 
     func1, # FUN == 1 
     func2, # FUN == 2 
     stop("function ", FUN, " not defined")) # default 
    appFun(arg1, arg2) 
} 
applyfunction(1,2,3) 
# [1] 5 
applyfunction(2,9,43) 
# [1] -34 
applyfunction(3,9,43) 
# Error in applyfunction(3, 9, 43) : function 3 not defined 
5

Jeśli naprawdę chcesz to zrobić „w liczbach”:

> applyfunction=function(n,a,b){get(paste("func",n,sep=""))(a,b)} 
> func1=function(a,b){a+b} 
> func2=function(a,b){a*b} 
> applyfunction(1,4,3) 
[1] 7 
> applyfunction(2,4,3) 
[1] 12 

Używa się i wklej, aby uzyskać funkcję związaną z nazwą.

+0

'match.fun' jest nieco lepsze od' dostać' do tego zastosowania. – hadley

+0

@ hadley: Dlaczego? Czy 'match.fun' nie nazwałbym' get' argumentami 'envir' i' mode' w tym przypadku? –

+0

Sprawdza również, czy znaleziony obiekt jest funkcją ... – hadley

0

A co z wykorzystaniem jednej z funkcji zmiennych jako przełącznika?

func1 <- function(x,y,z) { 
## Function One stuff goes here 
if (x == 1) { 
var1 <- 1 
} 
## Function Two stuff goes here 
if (x == 2) { 
var1 <- 2 
} 
return(var1) 
} 

I, można dostać się do korzystania z tej samej funkcji, za pomocą przełącznika jest zmienna „x”:

> func1(1,1,1) 
[1] 1 
> func1(2,1,1) 
[1] 2 
0

Oto alternatywna do przełączania lub pasty, wystarczy użyć indeksowania, aby wybrać z listy :

function1=function(a,b) a+b 
function2=function(a,b,c) a*b 
applyfunc <- function(n, aa, bb){ c(function1, function2)[[n]](aa,bb) } 
applyfunc(1, 4, 3) 
# [1] 7 
applyfunc(2, 4, 3) 
#[1] 12 
applyfunc(3, 4, 3) 
# Error in c(function1, function2)[[n]] : subscript out of bounds