Learning Objectives
- Define a function that takes arguments
- Return a value from a function
- Test a function
- Set default values for function arguments
- Get used to documenting your functions
Rmd (R markdown) file.lab04-first-last.Rmd, where first and last are your first and last names (e.g. lab04-gaston-sanchez.Rmd).Rmd file as an html document (default option).Rmd and html files to bCourses, in the corresponding lab assignment.Let’s consider a typical programming example that involves converting fahrenheit degrees into celsius degrees. The conversion formula is
\[ (F - 32) \times 5/9 = C \]
Here’s some R code to convert 100 fahrenheit degrees into Celsius degrees:
# fahrenheit degrees
fahr_deg = 100
# convert to celsius
(fahr_deg - 32) * (5/9)
## [1] 37.77778
What if you want to conver 90 fahrenheit degrees in Celsius degrees? One option would be to rewrite the previous lines as:
# 90 fahrenheit degrees to celsius
fahr_deg = 90
(fahr_deg - 32) * (5/9)
## [1] 32.22222
However, retyping many lines of code can be very boring, tedious, and inefficient. To make your code reusable in a more efficient manner, you will have to write functions.
Step 1: write code for a small and concrete example, and make sure that it works.
Step 2: encapsulate the code in the form of a function. You have to choose a name, some argument(s), and determine the output.
Here’s one example with a function fahrenheit_to_celsius(). You should always document your functions using the comments
#title
#description
#inputs (list each input separately)
#output
as shown in this example.
# title: farenheit celsius function
# description: converts farenheit to celsius
# inputs:
# - x: the farenheit value
# output:
# - computed celsius value
fahrenheit_to_celsius <- function(x) {
(x - 32) * (5/9)
}
fahrenheit_to_celsius(100)
## [1] 37.77778
If you want to get the conversion of 90 fahrenheit degrees, you just simply execute it again by changing its argument:
fahrenheit_to_celsius(90)
## [1] 32.22222
And because we are using arithmetic operators (i.e. multiplication, subtraction, division), the function is also vectorized:
fahrenheit_to_celsius(c(90, 100, 110))
## [1] 32.22222 37.77778 43.33333
Sometimes it is recommended to give a default value to one (or more) of the arguments. In this case, we can give a default value of x = 1. When the user executes the function without any input, fahrenheit_to_celsius returns the value of 1 fahrenheit degree to Celsius degrees:
fahrenheit_to_celsius <- function(x = 1) {
(x - 32) * (5/9)
}
# default execution
fahrenheit_to_celsius()
## [1] -17.22222
Write a function miles2kms() that converts miles into kilometers: 1 mile is equal to 1.6 kilometers. Give the argument a default value of 1. Include comments to document your function.
#title: miles to kilometers function
#description: converts miles to kilometers
#inputs:
# - x the mile value
#output:
# - kilometers value
miles2kms <- function(x = 1) {
(x) * (1.6)
}
According to Wikipedia, in 2015 the life expectancy of a person born in the US was 79 years. Consider the following question: Can a newborn baby in USA expect to live for one billion (\(10^9\)) seconds?
To answer this question, write a function seconds2years() that takes a number in seconds and returns the equivalent number of years. Include comments to document your function. Test the function with seconds2years(1000000000)
#title: seconds to years functions
#description: converts seconds to years
#inputs:
# - x the second value
#output:
# - years value
seconds2years <- function(x = 1) {
(x) / (3.154e+7)
}
seconds2years(1000000000)
## [1] 31.70577
Consider the following mathematical functions:
\[ f(x) = x^2, \qquad g(x) = 2x + 5 \]
Write two functions f() and g() based on the previous equations. Include comments to document your function.
#title: x squared function
#description: squares the value x
#inputs:
# - x
#output:
# - x squared
f <- function(x = 1) {
(x)^2
}
#title: random function
#description: multiplies x by 2 and adds 5
#inputs:
# - x
#output:
# - 2x+5
g <- function(x = 1) {
2*(x)+ 5
}
Test your functions with:
f(2)
## [1] 4
f(-5)
## [1] 25
g(0)
## [1] 5
g(-5/2)
## [1] 0
Write code to create the following composite functions. Include comments to document your function.
fog() for the composite function: \(f \circ g(x)\)
gof() for the composite function: \(g \circ f(x)\)
# your function fog()
#title: f of g
#description: inputs x into g then inputs the result into f
#inputs:
# - x
#output:
# - f(g(x))
fog <- function(x=1){
f(g(x))
}
# your function gof()
#title: g of g
#description: inputs x into f then inputs the result into g
#inputs:
# - x
#output:
# - g(f(x))
gof <- function(x=1){
g(f(x))
}
Test your composite functions with:
fog(2)
## [1] 81
fog(-5)
## [1] 25
gof(0)
## [1] 5
gof(-5/2)
## [1] 17.5
The pythagoras formula is used to compute the length of the hypotenuse, \(c\), of a right triangle with legs of length \(a\) and \(b\).
\[ c = \sqrt{a^2 + b^2} \]
pythagoras() version 1Write a function pythagoras() that takes two arguments a and b, and returns the length of the hypotenuse. Don’t forget to include comments to document your function!
Test your pythagoras() with two leg values: pythagoras(3, 4)
# your pythogras function
#title: Pythagorean theorem
#description: inputs a and b, squares a and b, sums the result and takes the square root of that result
#inputs:
# - a and b
#output:
# - sqrt(a^2+b^2)
pythagoras <- function(a=1, b=1){
sqrt(((a)^2) + ((b)^2))
}
pythagoras() version 2Modify your function pythagoras() so that argument b takes the same value of argument a. Include comments to document your function. Test it with just one leg value: pythagoras(5)
# your modified pythogras function
# your pythogras function
#title: Pythagorean theorem
#description: inputs a and a, squares a and a, sums the result and takes the square root of that result
#inputs:
# - a and a
#output:
# - sqrt(a^2+a^2)
pythagoras <- function(a=1){
sqrt(((a)^2) + ((a)^2))
}
In this problem we want to see whether the graph of a given polynomial will cross or touch the x axis in a given interval.
Let’s begin with the polynomial:
\[ f(x) = x^2 - 1 \]
The first thing to do is write a function for the polynomial, for instance:
poly1 <- function(x) {
x^2 - 1
}
Once you have a function for the polynomial, you can create a set of pairs of points \(x\) and \(y = f(x)\), and then use them to graph the polynomial
# set of points
x <- seq(-4, 4, length.out = 50)
y <- poly1(x)
# graph polynomial
plot(x, y, type = 'l', lwd = 3, col = "#FB7215", las = 1)
abline(h = 0, v = 0, col = '#888888aa', lwd = 1.5)
title(main = expression(paste(f(x), ' = ', x^2, (x - 1))))
Write functions and graph the following polynomials in the x-axis interval -4 to 4. Include comments to document your function:
# your code
#title: x cubed
#description: inputs x
#inputs:
# - x
#output:
# - x^3
polya <- function(x) {
x^3
}
# set of points
x <- seq(-4, 4, length.out = 50)
y <- polya(x)
# graph polynomial
plot(x, y, type = 'l', lwd = 3, col = "#FB7215", las = 1)
abline(h = 0, v = 0, col = '#888888aa', lwd = 1.5)
title(main = expression(paste(f(x), ' = ', x^3)))
# your code
# title: random function
# description: inputs x
# inputs:
# - x
# output:
# - (x^2 - 1)(x + 3)^3
polyb <- function(x){
((x^2) - 1)*((x) + 3)^3
}
# set of points
x <- seq(-4, 4, length.out = 50)
y <- polyb(x)
# graph polynomial
plot(x, y, type = 'l', lwd = 3, col = "#FB7215", las = 1)
abline(h = 0, v = 0, col = '#888888aa', lwd = 1.5)
title(main = expression(paste(f(x), ' = ',(x^2 - 1)(x + 3)^3)))
# your code
# title: random function
# description: inputs x
# inputs:
# - x
# output:
# - (x^2 - 1)(x^2 - 9)
polyc <- function(x){
(x^2 - 1)*(x^2 - 9)
}
# set of points
x <- seq(-4, 4, length.out = 50)
y <- polyc(x)
# graph polynomial
plot(x, y, type = 'l', lwd = 3, col = "#FB7215", las = 1)
abline(h = 0, v = 0, col = '#888888aa', lwd = 1.5)
title(main = expression(paste(f(x), ' = ',(x^2 - 1)(x^2 - 9))))