match.arg()

The match.arg() function is a handy function to assert if the input to a function argument is one (or more) of a pre-defined set of options.

Introduction

R being a dynamically typed programming language, it is good practice to verify the inputs provided through the arguments of your function. The verification needs to ensure that the function throws a sensible error if the function receives invalid inputs. The input may be invalid if a character string is passed through a function argument which the function expects to be a numeric value.

The match.arg() function in R's {base} package is one of a few built-in options you have to verify the input to a function.

Purpose

The purpose of the match.arg() function is to match the value of a function argument with one or more predefined choices. If no match is found, an error is thrown and if no value is provided for the argument, the first element from the predefined list of choices is used as a default value.

Usage

The signature of the match.arg() function is

match.arg(arg, choices, several.ok = FALSE)

where

  • arg is usually a single character string (i.e. a character vector of length one) but its length may be greater if several.ok is set to TRUE. Note that if arg is empty (i.e. a vector of length zero), it will throw an error. However, if it is NULL the function will return the first element of choices. The latter is a common way to use match.arg(), namely by using the first option as the default option if no value is provided for the argument.
  • choices is an optional character vector which provides the accepted choices, and
  • several.ok is a logical (i.e. logical vector of length one) to indicate if arg may have a length greater than one. The default is FALSE which means that we accept only a single character string.

Although you can call match.arg() at the command line in the global environment, the function should only be used inside another function.

Examples

The following two examples are functionally equivalent:

f <- function(status = c("unknown", "smoker", "nonsmoker")) {
    status <- match.arg(status)

    # ...do something with 'status'...

    status # return 'status' for the purpose of demonstration
}

and

f <- function(status) {
    status <- match.arg(status, choices = c("unknown", "smoker", "nonsmoker"))

    # ...do something with 'status'...

    status # return 'status' for the purpose of demonstration
}

The only difference being that the three available options do not appear in the function's signature (e.g. in the Usage section of the documentation) in the second form.

If we call the function f() from one of the examples above without a value for the status argument, match.arg() will select the first option as the default option. The arg argument to match.arg() is NULL in this case.

> f()
[1] "unknown"

One thing to be aware of is that match.arg() uses partial matching. This means that it will try to find a match with one of the options even if it is not a complete match. Using the example above, we do not have to set the status argument to smoker because even s will (partially) match the option we need:

> f("s")
[1] "smoker"

This behavior may or may not be what you want!

If match.arg() cannot find an unambiguous match, it will throw an error even if several.ok is set to TRUE:

> g <- function(color = c("lightgreen", "lightblue")) {
+   match.arg(color)
+ }
> g("l")

Error in match.arg(color): 'arg' should be one of “lightgreen”, “lightblue”

> g <- function(color = c("lightgreen", "lightblue")) {
+   match.arg(color, several.ok = TRUE)
+ }
> g("l")

Error in match.arg(color, several.ok = TRUE): 'arg' should be one of “lightgreen”, “lightblue”

Recommendation

The match.arg() function is definitely one that you should use in your own function definitions when you have a function argument that expects one (or more) value(s) from a predefined and finite set of choices. If no value is provided, match.arg() will conveniently return the first of the available choices as the default value.

If you use this function, use at the top of your function as in the examples above.

The partial matching of the choices may put you off or you may want the verification to throw a special class of error instead of the simpleError class returned by R's stop() function. If so, then you can achieve a similar result with the following alternative:

f <- function(status) {
    # the following three statements replace match.arg()
    # with a slightly stricter test for the 'status' argument
    status.choices <- c("unknown", "smoker", "nonsmoker")

    if(missing(status)) status <- status.choices[1]

    stopifnot(status %in% status.choices)

    # ...do something with 'status'...

    status # return 'status' for the purpose of demonstration
}

Now, if you provide the string "u" to the function, it will not partially match with the unknown option, but it will throw an error instead:

> f("u")

Error in f("u"): status %in% status.choices is not TRUE

Finally, you can use your own error function instead of R's stopifnot() function to throw an error with a special class of error.