2011-01-13 16 views
42

Diciamo che ho una funzione R in cui gli argomenti possono essere uno di alcuni valori denominati predefiniti (uno dei quali è l'impostazione predefinita) o un vettore di caratteri personalizzato. Come dovrei implementarlo senza fare affidamento su nomi di valori magici o su un'altra bandiera?Argomenti predefiniti della funzione e valori denominati

#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') 
    ... 
} 

risposta

6

mi piacerebbe usare qualche dataframe costante da qualche parte nel pacchetto:

.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

Dal tuo esempio abbiamo la scelta di "CORE" e "ALL". Se queste sono le due opzioni, le specifichiamo nella definizione della funzione per l'argomento 'members'. Es .:

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

Tale definizione funzione imposta i valori consentiti per argomento 'members', il valore predefinito è "CORE" in quanto questa è la prima opzione di nome.

Il codice che si utilizza all'interno del corpo della funzione è match.arg(), come @Joris ha già menzionato, ma poiché abbiamo impostato la funzione come sopra, possiamo semplicemente utilizzare il valore a match.arg(members}.

Così possiamo scrivere foo come:

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

che usiamo in questo modo:

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

notare il comportamento quando forniamo una stringa non incluso nel set di opzioni. Riceviamo un messaggio di errore intuitivo, tutto perché impostiamo le opzioni negli argomenti della funzione.

+0

Avendo scritto questo, non sono sicuro che tu voglia qualcosa per le opzioni "CORE" ', o' "ALL" 'o se vuoi memorizzare i due vettori di nomi da qualche parte. La mia risposta si rivolge alla prima, che è ciò a cui ho pensato quando ho letto il titolo della tua Q. –

+0

Ho bisogno che accetti foo ("3rdRate"). Fondamentalmente mi sto chiedendo quale sia la convenzione per implementare questi tipi di sottoinsiemi predefiniti. –

+1

@Gavin Non devi fare 'membri <- 'CORE'': se imposti' several.ok = T' in 'match.arg()'. Abbinerà solo il primo. O semplicemente 'match.arg (" CORE ")' senza specificare le opzioni fa lo stesso. Ho scelto di non specificare tutte le opzioni nella funzione, in quanto l'adattamento richiede ora solo l'adattamento della costante dataframe all'interno del pacchetto. Altrimenti dovrai adattare sia il frame dati che la funzione se vuoi aggiungere una nuova categoria. Una questione di design credo. Inoltre, l'utilizzo del costrutto try consente di specificare un vettore come richiesto dall'OP. –

Problemi correlati