c(1, 2, NA, 6)
Functions: Answers
Make sure that you try the exercises yourself first before looking at the answers
Function Arguments
Look at the help file for the function mean()
.
How many arguments does the function have?
What types of vectors are accepted?
What is the default setting for dealing with NA values?
Three arguments (plus further arguments).
Numerical and logical vectors are accepted.
The default setting is to NOT remove NA (missing) values.
Use the function mean()
to calculate the mean of the following values:
note the NA
and use named argument matching
mean(x = c(1, 2, NA, 6), na.rm = TRUE)
[1] 3
Do Q2 again but rearrange the arguments.
mean(na.rm = TRUE, x = c(1, 2, NA, 6))
[1] 3
Do Q2 again using positional matching.
mean(c(1, 2, NA, 6), 0, TRUE)
[1] 3
Determine the class of mean()
using class()
.
class(mean)
[1] "function"
The class is function
.
Determine the class of mean()
using str()
.
str(mean)
function (x, ...)
The class is function
.
Determine the class of the value output in Q4 using class()
.
class(mean(c(1, 2, NA, 6), 0, TRUE))
[1] "numeric"
The class is numeric
Determine the class of the value output in Q4 using str().
str(mean(c(1, 2, NA, 6), 0, TRUE))
num 3
The num
means the class is numeric
.
Function environment and scoping
For each of the following sets of commands, give the value that will be returned by the last command. Try to answer without using R.
<- 5
w <- function(y) {
f return(w + y)
}f(y = 2)
<- 5
w <- function(y) {
f <- 4
w return(w + y)
}f(y = 2)
This will return 7 because
w
is 5 and we are evaluating the function aty = 2
This will return 6 because
w
is reassigned as 4 inside the function and we are evaluating the function aty = 2
.
Among the variables w
, d
, and y
, which are global to f()
and which are local? What is the value of z when executing f(w)
<- 2
w <- function(y) {
f <- 3
d <- function(z) {
h return(z + d)
}return(y * h(y))
}
The object w
is global to f()
while d
and y
are local to f()
.
z
is 2, because it takes the value of y
when executing h(y)
in function f()
, which takes the value of global variable w
when executing f(w)
Do the following in R:
- Try:
<- function(a) {
myFun1 <- 3
b myFun2(a)
}
<- function(y) {
myFun2 return(y + a + b)
}
myFun1(10)
What happens?
- Now try:
<- 1
a <- 2
b myFun1(10)
What happens?
We get an error message because
a
andb
are local tomyFun1
so the functionmyFun2
can’t find them in the global environment.We get get the value 13 because the values
a
andb
are global somyFun2
can find them and use them in its commands.
if(), else, and ifelse() and Vectorization
Write a function called ‘evenOrOdd’ involving if
and else
that takes an argument x
and returns “Even” or “Odd” depending on whether or not x
is divisible by 2. (Do not use the ifelse() function).
<- function(x) {
evenOrOdd if(x %% 2 == 0) {
return("Even")
else {
} return("Odd")
} }
Is your function ‘evenOrOdd’ vectorized? Check by passing it the vector:
<- c(3, 6, 6, 4, 7, 9, 11, 6) w
evenOrOdd(w)
Error in if (x%%2 == 0) {: the condition has length > 1
An error is given, because x in if(x %% 2 == 0)
is longer than 1.
Another way to determine if each element of a vector is even or odd is to use the ifelse()
function, which serves as a vectorized version if
and else
. Use ifelse()
to obtain “Even” or “Odd” for each element of w
.
ifelse(w %% 2 == 0, "Even", "Odd")
[1] "Odd" "Even" "Even" "Even" "Odd" "Odd" "Odd" "Even"
Terminating a function with returns, errors, and warnings
The functions warning()
and stop()
are used to print a warning message and to stop the execution of the function call and print an error message. For example:
<- function(x) {
noNegMean if(all(x < 0)) {
stop("All values in x are negative")
}
if(any(x < 0)) {
< 0] <- 0
x[x warning("Negative values in x replaced by zero")
}
return(mean(x))
}
Copy the above code and then pass noNegMean()
a vector containing some negative and some positive values. What happens?
noNegMean(c(-1,0,1))
Warning in noNegMean(c(-1, 0, 1)): Negative values in x replaced by zero
[1] 0.3333333
We get the warning message and it returned 0.3333, which is the average of c(0, 0, 1)
.
What happens when you pass noNegMean()
a vector containing all negative values?
noNegMean(c(-1,-1,-1))
Error in noNegMean(c(-1, -1, -1)): All values in x are negative
We get the error message and nothing is returned.
Write a function ratio()
that takes two arguments, x
and y
, and attempts to compute the ratio x/y
.
If both x == 0 & y == 0
, the function should stop and print an error message about dividing 0 by 0.
If y == 0
(but not x), the function should print a warning message about dividing by 0, and then return x/y
(which will be Inf
).
In all other cases, it should return x/y
.
Test your ratio()
function first using two nonzero values for x
and y
, then using a nonzero x
but y = 0
, and finally using x = 0
and y = 0
.
<- function(x,y) {
ratio if(x == 0 & y == 0) {
stop("Cannot divide zero by zero.")
}
if(y == 0) {
warning("Cannot divide by zero.")
}
<- x/y
ratio return(ratio)
}
ratio(2,3)
[1] 0.6666667
ratio(0,0)
Error in ratio(0, 0): Cannot divide zero by zero.
ratio(1,0)
Warning in ratio(1, 0): Cannot divide by zero.
[1] Inf
looping using for() loops and the apply functions
Copy this is a function to determine if a number is a prime number:
<- function(num){
isPrime if (num == 2) {
return(TRUE)
}if(num > 1) {
for(i in 2:(num-1)) {
if ((num %% i) == 0) {
return(FALSE)
}
}else {
} return(FALSE)
}
return(TRUE)
}
Copy this matrix for which we would like to check if a number is a prime number:
<- matrix(1:100, nrow=10) mat
Use the apply()
function to calculate the prime number for each number in the matrix.
What numbers from 1 until 100 are prime numbers?
apply(mat, c(1,2), isPrime)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] FALSE TRUE FALSE TRUE TRUE FALSE TRUE TRUE FALSE FALSE
[2,] TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[3,] TRUE TRUE TRUE FALSE TRUE TRUE FALSE TRUE TRUE FALSE
[4,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[5,] TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[6,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[7,] TRUE TRUE FALSE TRUE TRUE FALSE TRUE FALSE FALSE TRUE
[8,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[9,] FALSE TRUE TRUE FALSE FALSE TRUE FALSE TRUE TRUE FALSE
[10,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
apply(mat, c(1,2), isPrime)] mat[
[1] 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Copy the following command to create a list containing two generations of the famous Kennedy family:
<- list(
Kennedys JosephJr = character(0),
John = c("Caroline", "JohnJr", "Patrick"),
Rosemary = character(0),
Kathleen = character(0),
Eunice = c("RobertIII", "Maria", "Timothy", "Mark", "Anthony"),
Patricia = c("Christopher", "Sydney", "Victoria", "Robin"),
Robert = c("Kathleen", "JosephII", "RobertJr", "David",
"MaryC", "Michael", "MaryK", "Christopher",
"Matthew", "Douglas", "Rory"),
Jean = c("Stephen", "William", "Amanda", "Kym"),
Edward = c("Kara", "EdwardJr", "Patrick")
)
Use a for()
loop to loop over the list of the first generation of Kennedys, keeping track of how many children each one has in a vector.
<- NULL
children for(i in Kennedys){
<- c(children, length(i))
children
} children
[1] 0 3 0 0 5 4 11 4 3
Now, using the lapply()
function, loop over the list of the first generation of Kennedys and keep track of how many children each Kennedy has. What is the class of the output?
<- lapply(Kennedys, length)
result result
$JosephJr
[1] 0
$John
[1] 3
$Rosemary
[1] 0
$Kathleen
[1] 0
$Eunice
[1] 5
$Patricia
[1] 4
$Robert
[1] 11
$Jean
[1] 4
$Edward
[1] 3
class(result)
[1] "list"
Answer Question 20 again using the sapply()
function. What is the class of the output?
<- sapply(Kennedys, length)
result result
JosephJr John Rosemary Kathleen Eunice Patricia Robert Jean
0 3 0 0 5 4 11 4
Edward
3
class(result)
[1] "integer"
Load the “diamonds” dataset from the ggplot2 package by running library(gglot2)
and calculate the average price of diamonds by color and clarity using the tapply()
function.
library(ggplot2)
tapply(diamonds$price, list(diamonds$color, diamonds$clarity), mean)
I1 SI2 SI1 VS2 VS1 VVS2 VVS1 IF
D 3863.024 3931.101 2976.146 2587.226 3030.159 3351.128 2947.913 8307.370
E 3488.422 4173.826 3161.838 2750.942 2856.294 2499.674 2219.820 3668.506
F 3342.182 4472.625 3714.226 3756.795 3796.718 3475.513 2804.277 2750.836
G 3545.693 5021.684 3774.787 4416.256 4131.362 3845.283 2866.821 2558.034
H 4453.414 6099.895 5032.415 4722.414 3780.689 2649.067 1845.658 2287.870
I 4302.185 7002.649 5355.020 5690.506 4633.184 2968.233 2034.862 1994.937
J 5254.060 6520.958 5186.048 5311.059 4884.461 5142.397 4034.176 3363.882