5.2 User defined functions
In this section we cover how to write your own user-defined functions (Section 5.2), which as the name suggests are functions you write yourself instead of using the built-in functions.
While there are hundreds of packages that can do everything that you need in R, it is often quicker to write a function to do something specific than it is to find someone else’s function. For purposes of scientific reproducibility, for automation and for clean code, wrapping chunks of code into functions is a must!
Crafting a function is pretty simple. We use the function()
command, and provide it with a name for our new function and some logic for that function to perform.
Below we create a very simple function called addOrMinus
:
addOrMinus <- function(a, b=2, add=TRUE) {
if (add) { # If the logical add is TRUE, then carry out this section
return(a + b) # Add a and b and return the result
} else { # or if add is FALSE, then do this instead
return(a - b) # Subtract b from a and return that result
}
}
What is happening here?
This function takes the following three arguments:
- a required numerical value named
a
, - an optional numerical value named
b
and - an optional logical value named
add
.
Arguments b
and add
are given default values of 2
and TRUE
respectively by using the equal (=) sign in the function declaration. These defaults values are used in the logic of the function if no other values are provided when the function is called.
You call the function using its name and specifying the input:
addOrMinus(1)
## [1] 3
addOrMinus(2, 4)
## [1] 6
and you can assign the answer to a new variable:
answer <- addOrMinus(2, add=FALSE, b=4)
Below is another example calculating the hypotenuse of a triangle:
hypotenuse <- function(a,b) {
return(sqrt(a^2+b^2))
}
hypotenuse(3,4)
What is happening here? This function takes two numbers and returns the square root of the sum of the squares of those two numbers.
Functions can contain any data-type as input, they can be simple data types (Section 2.3) or even the more complex data structures (Section 2.6). You can have a mixture of required and optional values. By convention, required arguments are listed first, then followed by any optional arguments.
Taking the above hypotenuse
function, the second number \(b\) can become optional by specifying a default value, such as:
hypotenuse2 <- function(a,b=3){
print(paste("a=",a,"and b=",b))
return(sqrt(a^2+b^2))
}
hypotenuse2(3)
## [1] "a= 3 and b= 3"
## [1] 4.242641
hypotenuse2(234,32)
## [1] "a= 234 and b= 32"
## [1] 236.1779
Creating and using functions
-
Try the examples above to create and experiment with the two functions.
-
Create a function that will perform the temperature conversion celsius to fahrenheit: \(F=\frac{9}{5}C+32\). Call the function
celsius.to.fahrenheit(minTemp\(X1996)</code> on temperatures from 1996 of our temperature data. Save this to a new variable <code>fahrenheit.1996</code>.</p></li> <li><p>Create another function to perform the ooposite conversion, from fahrenheit to celsius: <span class="math inline">\)C=(F-32)$. Call the function
fahrenheit.to.celsius(fahrenheit.1996)
, did you get the same results? -
Now try running either
celsius.to.fahrenheit
orfahrenheit.to.celsius
on the full matrixminTemp
.
Expected output for 2: Only the first 6 results are shown
## [1] "Before conversion:"
## [1] 23.4 23.5 24.7 17.8 20.4 20.5
## [1] "Convert to fahrenheit:"
## [1] 74.12 74.30 76.46 64.04 68.72 68.90