13.1 Input to functions
13.1.1 Default arguments
When you create functions with many inputs, you’ll probably want to start adding default values. Arguments with default values do not need to be specified by the user, as R will simply take the default. Most functions that you’ve used so far have default values. For example, type ?hist into the console. You can see that only the first argument x does not have a default value, while all other arguments, such as breaks, main, xlab etc. do have default values. Including defaults can save the user a lot of time because it keeps them from having to specify every possible input to a function.
Specifing default values in the function definition is very easy, just add = and then the default value after the input argument. For example, we could write a function that calculates the density of the square of a normal distribution. We want the arguments mean, sd and log to have default values:
> calculateDensitySquareOfNormal <- function(x, mean = 0, sd = 1, log = FALSE){
+ return(dnorm(x, mean, sd, log)^2)
+ }Now, R will set any inputs that the user does not specify to its default:
> x <- 0.6
> calculateDensitySquareOfNormal(x)
[1] 0.1110386
> calculateDensitySquareOfNormal(x, 1.473)
[1] 0.07427313
> calculateDensitySquareOfNormal(x, 1.473, 2.1)
[1] 0.0303618
> calculateDensitySquareOfNormal(x, 1.473, 2.1, TRUE)
[1] 3.053005Note that if we wanted e.g. to change sd to 2.1, but leave mean at its default value, we can not simply write
as R would interpret 2.1 as the input for mean. We either need to specify both mean and sd, or then (better!) name the arguments:
13.1.2 Dot-dot-dot (…) - the wildcard argument
Many functions in R take an arbitrary number of inputs:
How do these functions work? They rely on the special argument ... that captures any number of arguments that aren’t otherwise matched.
This becomes useful when you send those ... on to another function, e.g. when your function primarily wraps another function. For example, if you create a custom function that calls the histogram function hist() in R, you might also want the user to be able to specify optional inputs for the plot, like main, xlab, ylab, etc. However, it would be a real pain to have to include all possible plotting parameters as inputs to our new function:
> plotHistWithLegend <- function(x, text, breaks = "Sturges",
+ freq = NULL, probability = !freq,
+ include.lowest = TRUE, right = TRUE,
+ density = NULL, angle = 45, col = NULL, border = NULL){
+
+ # call hist()
+ hist(x, breaks = breaks, freq = freq, probability = probability, include.lowest = include.lowest, right = right, density = density, angle = angle, col = col, border = border)
+ # do extra stuff
+ legend("topright", legend = text)
+ }… and these are not even all parameters hist() accepts! Thankfully, we can take care of all of this by using ... as an input to the function. Note that the ... notation will only pass arguments on to functions that are specifically written to allow for optional inputs. Luckily, hist() allows this (check the help page). The ... input tells R that the user might add additional inputs that should be used later in the function. Hence, ... is a very useful catch-all for function wrappers. Let’s re-write our function accordingly:
> plotHistWithLegend <- function(x, text, ...){
+ # call hist()
+ hist(x, ...)
+ # do extra stuff
+ legend("topright", legend = text)
+ }
> plotHistWithLegend(rnorm(100), "legend no one needs",
+ xlab = "random numbers")
Whatever parameters we give to our function plotHistWithLegend() (for example xlab), it will just pass them on to hist(), which will use them if it finds a matching argument.
The ... argument captures all arguments passed unless they were either parsed before (i.e. they occur prior to ... in the list of arguments) or they are named. Consider for instance the following (admittedly useless) function:
In the above call to unexpectedSum, the first argument passed was attributed to x and all others to .... As a consequence, the sum excludes the first value. This is why built-in functions such as sum(), min() or max() that process an arbitrary number arguments are defined with the ... argument at the first position. In case of sum(), for instance, the definition is sum(..., na.rm = FALSE). However, that also has side-effects: Suppose we would like to exclude NA from the sum:
Oh wait, 1 + 2 + 3 = 7 ?!? Of course not, but the the fourth argument TRUE is not attributed to the argument na.rm, but also to ... and coerced to 1. In order to prevent that, the arguments not meant to be included in ... need to be named:
13.1.3 Exercises: Input to functions
See Section 18.0.33 for solutions.
- Write a function that returns a variable raised to the power of another variable: . Variable
yshould have a default argument.