Chapter 5 Functions in R
You can download the R Markdown file used to generate this document (or webpage) here. I would encourage you to download that Rmd file, open it own your own computer in RStudio, and run the code chunks on your own (and modify things as you wish!).
In this tutorial,
- We’ll go over argument order and default values when calling functions in R
- We’ll go over the basics of writing functions in R
5.1 Argument order and default values
As you encountered last week, R has many built-in functions (e.g., abs
, round
, etc), and all of R packages that you install provide even more functions that you can use.
Using an existing function is simple.
Write the name of the function you want to use followed by the requisite arguments in parentheses.
For example,
<- -15
value abs(value)
## [1] 15
or,
log(4, base=2)
## [1] 2
If you look at the documentation for abs
(enter ?abs
into your R console), there’s only one argument (x
), and x
is required (i.e., notice that it has no default values).
In contrast, run ?log
function in your R console.
Notice that there are two possible arguments for log
, x
and base
.
x
is required, as it has no default value, but base
is optional, defaulting to exp(1)
if not provided.
Let’s say we want to take the \(log_3\) of 27.
To do so, we’ll need to specify both the x
and base
arguments, but there are a few ways that we can do that.
For example, we could call log
with each argument in the correct position:
log(27, 3)
## [1] 3
We could call log
as I did above with log(4, base=2)
:
log(27, base=3)
## [1] 3
In this case, R relies on argument position to deduce which argument is which up until the first named variable.
We could also specify all arguments using their names:
log(x=27, base=3)
## [1] 3
If you specify arguments this way (using their names), argument order doesn’t matter.
log(base=3, x=27)
## [1] 3
When calling a function with multiple arguments, I strongly encourage you to specify arguments by name.
5.2 Writing your own functions
To write a function in R, the general structure is as follows:
<- function(parameters) {
my_function # Perform some actions using the given parameters.
# Optionally, return some value
}
We can write a function that rolls a die for us like so:
# This function rolls a six-sided die.
# Run ?sample in your console if you're curious about how the sample function
# works.
<- function() {
roll <- sample(x = 1:6, size = 1, replace = TRUE)
result return(result)
}
Currently, roll_d6
will always simulate rolling a six-sided die.
We could modify our function definition to add an argument that specifies the size of the die:
# This function simulates rolling a die with a given number of sides.
<- function(sides) {
roll <- sample(x = 1:sides, size = 1, replace = TRUE)
result return(result)
}
Note that when we run the code chunk above, we are redefining our roll
function.
Challenge question: Try writing your own roll function that rolls an argument-specified number of dice (where the number of sides of each die is specified by an argument) and then returns the sum of those rolls.
5.3 Return values
In the roll
functions that we wrote, we explicitly specified what the functions should return.
However, if you do not use return()
to specify what should be returned, the last evaluated expression is returned automatically.
If the last evaluated expression doesn’t produce a value, your function will not return a value.
I generally prefer to use explicit return statements because it lets me quickly identify what my functions are returning.
Here’s a silly function:
<- function(a) {
silly_function if (a == 1) {
+ 100
a else if (a == 2) {
} 200
else if (a == 3) {
} return(300)
else {
}
} }
Try calling silly_function
with different inputs to see what it returns.
5.4 Default argument values
Just like many built-in functions have some arguments with defualt values, you can define your functions such their arguments have default values. All you need to do is specify the default value of an argument when you define the function.
For example, if we wrote a function that calculates the price something with a sales tax included, we might specify a default tax rate for convenience.
<- function(price, tax_rate=0.06) {
price_with_tax return(price+(price*tax_rate))
}