In this article, you will learn how to write your own functions in R. Specifically, we will cover:
- How to write a simple function
- How to write a more complex function
- How to write an anonymous function
- How to write a function with an unfixed number of arguments
- How to write a recursive function
1. Writing a simple function
Let’s define a new function divide that takes 2 arguments a and b and returns a / b:
divide = function(a, b) { a / b } # divide(1, 1) returns: 1 # divide(1,2) returns: 0.5 # divide(a = 1, b = 2) also returns: 0.5
Normally, a function returns the last expression written inside the curly braces: { }. (In our example above, the last written expression inside the function is: a / b)
If you want, you can choose to return another value by using return(). This will force the function to stop and return the expression inside of return().
For example:
divide = function(a, b) { return(a - b) # stop and return a - b a / b # this line will be ignored } # divide(1, 1) returns: 0 # divide(1,2) returns: -1
2. Writing a more complex function
We can expand our function to check whether the user’s inputs are numbers; If not, the function should return an error message.
We can return error messages by using stop():
divide = function(a, b) { # checking if a or b are not numeric values if (!is.numeric(a) || !is.numeric(b)) { stop("The function expects numeric values") } else { a / b } } # divide(1, 'x') returns: Error in divide(1, "x") : The function expects numeric values # divide(1, 1) returns: 1 # divide(1,2) returns: 0.5
Our function still has a obvious problem:
The current version of divide outputs Inf when we divide by zero.
divide(1, 0) # outputs: Inf
So, we can use warning() to return a warning message when the users tries to divide by zero.
Note that here we are returning a warning not an error because the division by zero can be executed (after all, R does return an answer: Inf), but the answer may not be anticipated by the user.
divide = function(a, b) { # checking if a or b are not numeric values if (!is.numeric(a) || !is.numeric(b)) { stop("The function expects numeric values") } # if b is 0, return an error message else if (b == 0) { warning("Division by zero") } else { a / b } } # divide(3, 0) outputs: Warning message: # In divide(1, 0) : Division by zero
3. Writing an anonymous function
An anonymous function provides a shortcut to write a simple function. Since the anonymous function has no name, it cannot be referenced/used elsewhere in the code.
The syntax is:
function(input) output
For example:
sapply(c(1,2,3), function(x) 1/x) # sapply applies the anonymous function to c(1,2,3) # and outputs: 1.0000000 0.5000000 0.3333333
But, we still have a problem when we divide by zero:
sapply(c(1,2,3,0), function(x) 1/x) # outputs: 1.0000000 0.5000000 0.3333333 Inf
So, we can include an if-else statement inside the anonymous function to handle division by zero as follows:
sapply(c(1,2,3,0), function(x) {if (x != 0) 1/x else NA}) # outputs: 1.0000000 0.5000000 0.3333333 NA
4. Writing a function with an unfixed number of arguments
We can use the 3 dots to specify that a function takes an undetermined number of arguments.
For example:
add = function(...) { sum(...) } # add(1,2,3) returns: 6 # which is: 1 + 2 + 3
You can pass the “…” argument to another function inside of your function.
For example:
random.plot = function(n_points, ...) { x = 1:n_points y = rnorm(n_points) plot(x, y, ...) } set.seed(1) random.plot(100)
Output:
So when we specify col = “red”, it will be passed to the function plot inside of our custom function:
set.seed(1) random.plot(100, col = 'red')
Output:
5. Writing a recursive function
A recursive function is a function that calls itself (i.e. defined in terms of itself).
For example:
factorial = function(n) { # if n is 0 or 1, the answer is 1 if (n == 0 || n == 1) { return(1) # done } # else the function will continue calling itself # each time with a smaller n, # until we get to n = 1 else { return(n * factorial(n-1)) # recursive call } } # factorial(3) outputs: 6
Here’s an illustration that represents how the function works when we call factorial(3):