Loading Packages
library(tidyverse)
library(stringr)
Example function
Create the mySum() function, and use it to calculate the sum of 13 and 1989.
mySum <- function(number1, number2) {
return(number1 + number2)
}
# Defaulting to order of arguments in function
mySum(13, 1989)
## [1] 2002
What happens when we calculate the sum of NA and 1989?
Answer: It is NA
## [1] NA
Best practices
Read the source code for each of the following three functions, determine the purpose of each function, and propose better function names.
Answer: The first i will be changing is the naming convention f1, f2 and f3 are poor naming convention
startsWithPrefix <- function(string, prefix) {
str_sub(string, 1, nchar(prefix)) == prefix
}
startsWithPrefix("Hello, world!", "Hello")
## [1] TRUE
removeLastElement <- function(x) {
if (length(x) <= 1) return(NULL)
x[-length(x)]
}
removeLastElement(c(1, 2, 3, 4))
## [1] 1 2 3
harmonicMean <- function(x) {
1 / (mean(1 / x))
}
harmonicMean(c(2, 4, 6))
## [1] 3.272727
Create a new function to calculate the geometric mean of a vector of numbers which is equal to the nth root of the product of n numbers.
geometricMean <- function(x) {
if (length(x) == 0) {
stop("Input vector must not be empty.")
}
if (any(x <= 0)) {
stop("Input vector must contain positive numbers only.")
}
n <- length(x)
geom_mean <- prod(x)^(1/n)
return(geom_mean)
}
geometricMean(c(5,2))
## [1] 3.162278
Conditional execution, warnings, and errors
Create a function called is.whole.number(), which checks if a given value is a whole number (e.g., 0, 1, 2, …) or not.
is.whole.number <- function(value) {
if (is.integer(value) || (is.numeric(value) && value %% 1 == 0)) {
return(TRUE)
} else {
return(FALSE)
}
}
is.whole.number(4) # Returns TRUE
## [1] TRUE
is.whole.number(3.0) # Returns TRUE
## [1] TRUE
is.whole.number(3.5) # Returns FALSE
## [1] FALSE
The ^ operator raises a number to a specified power in R. Create a function that raises a number to a specified power, and returns a warning and an NaN value if the number is negative and the power is not a whole number.
raiseToPower <- function(base, exponent) {
if (base >= 0 || is.whole.number(exponent)) {
return(base^exponent)
} else {
warning("Base is negative and exponent is not a whole number!")
return(NaN)
}
}
# Use your function to calculate 4^(2), (-9)^(2), 3^(1/3), and (-3)^(1/3).
raiseToPower(4, 2)
## [1] 16
## [1] 81
## [1] 1.44225
## [1] NaN
The ifelse() function
Create the myNewSum() function, and use it to calculate the sum of 13 and 1989
# Creating a function called mySum with 2 required arguments, 1 optional argument
myNewSum <- function(number1, number2, remove.na = TRUE) {
if(remove.na) {
calcSum <- ifelse(is.na(number1), 0, number1) +
ifelse(is.na(number2), 0, number2)
} else {
calcSum <- number1 + number2
}
return(calcSum)
}
What happens when we calculate the sum of NA and 1989 using myNewSum()?
## [1] 1989
Logical operators
Does the code (1:4 < 4) & (1:4 > 1) produce the same result as (1:4 < 4) && (1:4 > 1)? Which code achieves what appears to be its intended purpose?
Answer: No, the code (1:4 < 4) & (1:4 > 1) does not produce the same result as (1:4 < 4) && (1:4 > 1). The & operator performs element-wise logical AND operation on the corresponding elements of the two vectors, while the && operator performs a single logical AND operation considering only the first element of each vector.