2011-01-13 2 views
42

Предположим, что у меня есть функция R, в которой аргументы могут быть одним из нескольких предопределенных именованных значений (один из которых является значением по умолчанию) или пользовательский вектор символов. Как это реализовать, не полагаясь на имена магических значений или другой флаг?Параметры аргументов по умолчанию и именованные значения

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

ответ

6

Я хотел бы использовать некоторую постоянную dataframe где-то в пакете:

.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

Из вашего примера мы имеем выбор "CORE" и "ALL". Если это два параметра, то мы укажем их в определении функции для аргумента 'members'. Например .:

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

Это определение функции устанавливает допустимые значения аргумента 'members', значение по умолчанию "CORE", поскольку это первый названный вариант.

Код, который используется в теле функции, равен match.arg(), поскольку @Joris уже упомянул, но поскольку мы установили функцию вверху, как описано выше, мы можем просто использовать только match.arg(members}.

Таким образом, мы можем написать foo как:

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

, которые мы используем, как это:

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

Обратите внимание на поведение, когда мы поставляем строку не входит в набор опций. Мы получаем интуитивное сообщение об ошибке, потому что мы настраиваем параметры в аргументах функции.

+0

Написав это, я не уверен, хотите ли вы что-то для опций '' CORE '' или '' ALL ''или хотите ли вы где-то сохранить два вектора имен. Мой ответ затрагивает первое, о чем я думал при чтении названия вашего Q. –

+0

Мне нужно, чтобы он принял foo («3rdRate»). В основном мне интересно, что такое соглашение для реализации этих типов предопределенных подмножеств. –

+1

@Gavin Вам не нужно делать 'members <- 'CORE'': если вы установите' multiple.ok = T' в 'match.arg()'. Он будет соответствовать только первому. Или просто 'match.arg (« CORE »)' без указания опций делает то же самое. Я решил не указывать все опции в функции, так как адаптация теперь требует только адаптации константы dataframe в пакете. В противном случае вам придется адаптировать как фрейм данных, так и функцию, если вы хотите добавить новую категорию. Я думаю, вопрос дизайна. Плюс, используя конструкцию try, можно специфицировать вектор как запрошенный OP. –

Смежные вопросы