Functions are tools

``````mean()

sum()

sd()
``````

• To set specific defaults to other functions.
• Avoid repetition of large chunks of code.

E.g., set defaults for nice plots

``````plot(1:10)
``````

``````par(lwd = 2, tcl = 0.3,
font.lab = 2, las = 1,
cex = 1.5, cex.lab = 1.5, cex.axis = 1.5,
mar = c(5,5,2,2))
plot(1:10)
``````

Functions are an abstraction

``````# Calculate the mean of your data

sum(my.data) / length(my.data)
``````

We can separate what we want to do from how we do it.

``````# Function to calculate mean
my.mean <- function(x){
sum(x) / length(x)
}

# Calculate mean of my data
my.mean(my.data)
``````

This code is shorter but harder to understand

``````data\$response.logit <- log(data\$response / (1 - data\$response))
``````

This code is more lines, but:

• separates the what from the how,

• is more reliable.

``````logit <- function(p){
log(p / (1-p))
}

data\$response.logit <- logit(data\$response)
``````

Functions help avoid coding errors

• Functions are self-contained (e.g., do not depend on global variables)

• Limit the scope of variables, because they are contained within function body.

• Enable easy re-use of code.

• Project becomes more modular and easy to change.

How functions work

1. Take an object

2. Perform an action/s

3. Return another object or output

The structure of a function

1. Name: Can be any valid name. Do not write over existing functions. Follow style guide to function names.

2. Input arguments: What are the inputs or data to the function? As many inputs as you want.

3. Actions: What do you want the function to do with the inputs? Create a plot? Calculate a statistic? Run a regression analysis?

4. Action arguments: Are there any options and/or defaults you want to set?

5. Output: What output or final product do you want? A scalar? A vector? A dataframe? A plot? A table?

Structure of a function: Code

``````# The basic structure of a function

NAME <- function(ARGUMENTS) {

ACTIONS

return(OUTPUT) # Optional

}
``````

An example function

``````# Create the function my.mean()

my.mean <- function(x) {   # Single input called x

output <- sum(x) / length(x) # Calculate output

return(output)  # Return output to the user after running the function

}
``````

Or ..

``````# Create the function my.mean()

my.mean <- function(x) {   # Single input called x

sum(x) / length(x) # Calculate output

}
``````

Abstracting Functions

e.g., Calculate mean DBH of trees

i. Directly using the data

``````sum(dat_tree\$DBH) / length(dat_tree\$DBH)
``````

ii. Turn this into a function

``````my_mean <- function(dat_tree\$DBH){

sum(dat_tree\$DBH) / length(dat_tree\$DBH)

}
``````

iii. Abstract it

``````my_mean <- function(x){

sum(x) / length(x)

}
``````

Functions within functions

You can call functions from within functions.

We already did this in the function above, where we used sum() and length().

``````my_mean <- function(x){

sum(x) / length(x)

}
``````

e.g., return SD and mean tree DBH

``````meanSD <- function(x){

out <- c( my_mean(x), sd(x) )

return(out)

}
``````

• Multiple inputs

• Set defaults

• Store your functions in a new `customFunctions.R` file.

• Use source() to load that file into R

``````source("customFunctions.R")
``````

Build and test functions

• Build functions step-by-step.

• Test each line.

• Test full function on known inputs.

1. Use verbs for function names …

``````# Good

checkNames()

calcBA()

nameChecker()

baCalculator()
``````

… a different style from variables

``````# Variables

names_original

names_checked

tree_dbh

tree_ba

``````

2. Indent multiple lines to where definition starts

``````# Good

checkNames <- function(x,
names_correct = 'file-of-correct-names.txt'
) {
# Code of function body goes here, indented

}

checkNames <- function(x,
names_correct = 'file-of-correct-names.txt') {
# Here it is hard to tell the arguments from the code body
}

``````

3. No line breaks within assignments

``````# Good

calcCarbon <- function(dbh, height,
genus = 'Quercus')

calcCarbon <- function(dbh, height, genus =
'Quercus')

``````

4. Use comments to explain why, not what or how

Each line of comment should begin with a hash and a single space.

``````# A comment explains why

``````

5. Function documentation

There are many ways to document your functions.

It should include:

• Describe the function.
• List and describe the arguments, including data type.
• Describe what is returned.

• Comments should be sufficient and separate from the code.
``````# One example

funcName <- function(x, a, b,
arg1 = 'bananas',
arg2 = 6.45) {
# A short description of what the function does
#
# Arguments:
# Followed by a list of the arguments and description
#   x: data from ..., numeric
#   a: something, numeric
#   b: something else, numeric
#   arg1: type of fruit, character
#   arg2: a constant modifier, numeric
#
# Returns:
#   The total biomass of fruit in a forest

code body here

}
``````

Lists

Not that kind of list

Make a list with `list()`

``````# A simple list of three integers
x <- list(1, 2, 3)

str(x)
#> List of 3
#>  \$ : num 1
#>  \$ : num 2
#>  \$ : num 3

# We can name each part of the list
x_named <- list(a = 1, b = 2, c = 3)

str(x_named)
#> List of 3
#>  \$ a: num 1
#>  \$ b: num 2
#>  \$ c: num 3
``````

Lists can contain different types of objects

``````y <- list("a", 1, 1.5, TRUE)

str(y)
#> List of 4
#>  \$ : chr "a"
#>  \$ : int 1
#>  \$ : num 1.5
#>  \$ : logi TRUE
``````

Lists can contain other lists

``````z <- list(list(1, 2), list(3, 4))

str(z)
#> List of 2
#>  \$ :List of 2
#>   ..\$ : num 1
#>   ..\$ : num 2
#>  \$ :List of 2
#>   ..\$ : num 3
#>   ..\$ : num 4
``````

Three ways to subset a list

``````# An example list
a <- list(a = 1:3, b = "some text", c = pi, d = list(4, 5))

# The structure of 'a'
str(a)
#> List of 4
#>  \$ a: int [1:3] 1 2 3
#>  \$ b: chr "some text"
#>  \$ c: num 3.14
#>  \$ d:List of 2
#>   ..\$ : num 4
#>   ..\$ : num 5
``````

You can use:

1. `[ ]`
2. `[[ ]]`
3. `\$`

1. `[ ]` extracts a sub-list.

• The result will always be a list.
• You can use position …
``````str(a[1:2])
#> List of 2
#>  \$ a: int [1:3] 1 2 3
#>  \$ b: chr "some text"
``````
• … or name
``````str( a[c("a", "b")] )
#> List of 2
#>  \$ a: int [1:3] 1 2 3
#>  \$ b: chr "some text"
``````

2. `[[ ]]` extracts a single component from a list.

• It removes a level of hierarchy from the list.
``````str(a[[1]])
#> int [1:3] 1 2 3
``````

3. `\$` works for named elements in a list.

• Works like `[[ ]]`, except quotes are not needed.
``````str(a[["a"]])
#> int [1:3] 1 2 3

str(a\$a)
#> int [1:3] 1 2 3
``````

Updated: 2017-10-03