函数默认参数和命名值

时间:2011-01-13 17:57:34

标签: function r

假设我有一个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')
  ...
}

2 个答案:

答案 0 :(得分:59)

从您的示例中,我们可以选择"CORE""ALL"。如果这两个选项,那么我们在参数'members'的函数定义中指定它们。 E.g:

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”

请注意我们提供未包含在选项集中的字符串时的行为。我们得到一个直观的错误消息,因为我们在函数参数中设置了选项。

答案 1 :(得分:9)

我在包中的某处使用了一些常量数据框:

.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"