2011-01-13 19 views
42

Digamos que tengo una función R en la que los argumentos pueden ser uno de los pocos valores con nombre predefinidos (uno de los cuales es el predeterminado) o un vector de caracteres personalizado. ¿Cómo debo implementar esto sin confiar en los nombres de valores mágicos u otra bandera?Función de argumentos predeterminados y valores con nombre

#allow use of predefined subsets or pass their own list 
bratPack<-function(members='CORE',...){ 
    if (members=='CORE') 
    members<-c('Emilio Estevez','Anthony Michael Hall','Rob Lowe','Andrew McCarthy','Demi Moore','Judd Nelson','Molly Ringwald','Ally Sheedy') 
    else if (members=='ALL') 
    members<-c('Emilio Estevez','Anthony Michael Hall','Rob Lowe','Andrew McCarthy','Demi Moore','Judd Nelson','Molly Ringwald','Ally Sheedy','James Spader','Robert Downey, Jr.','Jon Cryer', 'John Cusack', 'Kevin Bacon', 'Jami Gertz', 'Mary Stuart Masterson', 'Matthew Broderick', 'Sean Penn', 'Kiefer Sutherland') 
    ... 
} 

Respuesta

6

que haría uso de alguna trama de datos constante en alguna parte en el paquete:

.mdata <- data.frame(
    CORE= c(TRUE,FALSE,TRUE), 
    OLD = c(TRUE,TRUE,FALSE), 
    ALL = c(TRUE,TRUE,TRUE), 
    row.names=c("John Doe", "Jan Janssen", "Piet Peters") 
) 

bratPack<-function(members='CORE',...){ 
    m.tmp <- try(
     match.arg(members,names(.mdata),several.ok=T), 
     silent=T) 

    if(!is(m.tmp,"try-error")) 
    members <- rownames(.mdata)[.mdata[[members]]] 

    print(members) 
} 

> bratPack('CORE') 
[1] "John Doe" "Piet Peters" 

> bratPack('Jan Janssen') 
[1] "Jan Janssen" 

> bratPack(c("John Doe","Dick Dickers")) 
[1] "John Doe"  "Dick Dickers" 
52

de su ejemplo tenemos la opción de "CORE" y "ALL". Si esas son las dos opciones, entonces las especificamos en la definición de la función para el argumento 'members'. Ej .:

foo <- function(x, members = c("CORE", "ALL")) { 
    ## do something 
} 

Esa definición de función establece los valores permitidos para el argumento 'members', su valor predeterminado es "CORE" ya que esta es la primera opción llamada.

El código que uno usa dentro del cuerpo de la función es match.arg(), como @Joris ya lo mencionó, pero como hemos configurado la función como arriba, podemos simplemente usarla para solo match.arg(members}.

Así podemos escribir foo como:

foo <- function(x, members = c("CORE", "ALL")) { 
    ## evaluate choices 
    members <- match.arg(members) 
    ## do something 
    print(members) 
} 

que utilizamos como esto:

> foo() 
[1] "CORE" 
> foo(members = "CORE") 
[1] "CORE" 
> foo(members = "ALL") 
[1] "ALL" 
> foo(members = "3rdRate") 
Error in match.arg(members) : 'arg' should be one of “CORE”, “ALL” 

observar el comportamiento cuando suministramos una cadena no incluido en el conjunto de opciones. Recibimos un mensaje de error intuitivo, todo porque configuramos las opciones en los argumentos de la función.

+0

Habiendo escrito esto, no estoy seguro de si desea algo para las opciones '" CORE "' o '" ALL "' o si desea almacenar los dos vectores de nombres en alguna parte. Mi respuesta se dirige a la primera, que es lo que pensé al leer el título de tu Q. –

+0

. Necesito que acepte foo ("3rdRate"). Básicamente, me pregunto cuál es la convención para implementar estos tipos de subconjuntos predefinidos. –

+1

@Gavin No tiene que hacer 'members <- 'CORE'': si establece' several.ok = T' en 'match.arg()'. Simplemente coincidirá con el primero. O simplemente 'match.arg (" CORE ")' sin especificar las opciones hace lo mismo. Opté por no especificar todas las opciones en la función, ya que la adaptación ahora solo requiere la adaptación de la constante del marco de datos dentro del paquete. De lo contrario, deberá adaptar tanto el marco de datos como la función si desea agregar una nueva categoría. Una cuestión de diseño, supongo. Además, el uso de la construcción try permite la especificación de un vector como OP preguntó. –

Cuestiones relacionadas