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

Note that if we wanted e.g. to change sd to 2.1, but leave mean at its default value, we can not simply write

> calculateDensitySquareOfNormal(x, 2.1)
[1] 0.01677481

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:

> calculateDensitySquareOfNormal(x, 0, 2.1)
[1] 0.03326051
> calculateDensitySquareOfNormal(x, sd = 2.1)
[1] 0.03326051

13.1.2 Dot-dot-dot (…) - the wildcard argument

Many functions in R take an arbitrary number of inputs:

> sum(1, 2, 3)
[1] 6
> sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
[1] 55

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.

13.1.3 Exercises: Input to functions

See Section 18.0.32 for solutions.

  1. Write a function that returns a variable raised to the power of another variable: xy. Variable y should have a default argument.