21 July 2016
Repetitive processes
Nothing may exist for our purpose
A function has three main parts
formals() - The arguments supplied to a functionbody() - This is the code inside the functionenvironment() - Where the function was createdformals(sd)
## $x ## ## ## $na.rm ## [1] FALSE
body(sd)
## sqrt(var(if (is.vector(x) || is.factor(x)) x else as.double(x), ## na.rm = na.rm))
environment(sd)
## <environment: namespace:stats>
This is telling us that sd() comes from the packages stats
f <- function(x) {
x + 1
}
What would the formals() be?
What would the body() be?
What would the environment() be?
Let's use our function
f(1:5)
## [1] 2 3 4 5 6
Where does the function look for it's values?
x <- 3
f <- function(x) {
x + 1
}
What would we expect to see if we don't provide x?
f()
## Error in f(): argument "x" is missing, with no default
Where does the function look for it's values?
x <- 3
f <- function(y) {
x + 1
}
Now what would we expect to see if we don't provide y?
f()
## [1] 4
Environment one level up.Place the following in a new script called myMean.R
myMean <- function(x){
total <- sum(x)
n <- length(x)
mn <- total / n
return(mn)
}
Select all, and hit Ctrl + Enter to send it to your Environment
What are the formals()?
Let's call our function
testVec <- 1:10 myMean(testVec)
## [1] 5.5
x = testVec when we called the functionmn as the last lineWhat if an idiot called our function?
What if an idiot called our function?
Add some comments
myMean <- function(x){
total <- sum(x) # Get the total of all elements
n <- length(x) # Count how many elements there are
mn <- total / n # Calculate the mean
return(mn)
}
NB: The comments are not reproduced by body(myMean)
What might I do in 6 months which is not intelligent?
What might I do in 6 months which is not intelligent?
The biggest issue will be missing values.
Let's create a vector with missing values
testVec <- c(NA, 1:10) myMean(testVec)
## [1] NA
How can we figure out where the problem is?
Let's create a vector with missing values
testVec <- c(NA, 1:10) myMean(testVec)
## [1] NA
We can use the command browser() to stop the function, and look inside it's Environment
EnvironmentmyMean <- function(x){
total <- sum(x) # Get the total of all elements
n <- length(x) # Count how many elements there are
browser()
mn <- total / n # Calculate the mean
return(mn)
}
The next time we call the function:
browser()Script WindowWe are now in the internal Environment for the function
total and n are shown in the Environment TabxCtrl + Enter (we can't edit this script)browser by hitting Stop (the red button)Where have things gone wrong?
total <- sum(x) has clearly failedn the correct value?Where have things gone wrong?
total <- sum(x) has clearly failedn the correct value?How can we remove the NA values?
CLICK THE STOP BUTTON!!!
na.rmna.rm = TRUEmyMean <- function(x, na.rm = TRUE){
if (na.rm){
x <- x[!is.na(x)]
}
total <- sum(x) # Get the total of all elements
n <- length(x) # Count how many elements there are
browser()
mn <- total / n # Calculate the mean
return(mn)
}
We only have to specify this if we want na.rm = FALSE
Call the function again:
myMean(testVec)
What did x[!is.na(x)] do?
Now we've protected our future selves, we can remove this line
myMean <- function(x, na.rm = TRUE){
if (na.rm){
x <- x[!is.na(x)]
}
total <- sum(x) # Get the total of all elements
n <- length(x) # Count how many elements there are
# browser()
mn <- total / n # Calculate the mean
return(mn)
}