==========
mean()
sum()
sd()
To perform specific tasks for your own work
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)
# Calculate the mean of your data
sum(my.data) / length(my.data)
# 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 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.
Take an object
Perform an action/s
Return another object or output
Name: Can be any valid name. Do not write over existing functions. Follow style guide to function names.
Input arguments: What are the inputs or data to the function? As many inputs as you want.
Actions: What do you want the function to do with the inputs? Create a plot? Calculate a statistic? Run a regression analysis?
Action arguments: Are there any options and/or defaults you want to set?
Output: What output or final product do you want? A scalar? A vector? A dataframe? A plot? A table?
# The basic structure of a function
NAME <- function(ARGUMENTS) {
ACTIONS
return(OUTPUT) # Optional
}
# 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
}
# Create the function my.mean()
my.mean <- function(x) { # Single input called x
sum(x) / length(x) # Calculate output
}
Problem: e.g., Calculate mean DBH of trees
sum(dat_tree$DBH) / length(dat_tree$DBH)
my_mean <- function(dat_tree$DBH){
sum(dat_tree$DBH) / length(dat_tree$DBH)
}
my_mean <- function(x){
sum(x) / length(x)
}
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)
}
meanSD <- function(x){
out <- c( my_mean(x), sd(x) )
return(out)
}
Multiple inputs
Set defaults
source()
your functionsStore your functions in a new customFunctions.R
file.
Use source()
to load that file into R
source("customFunctions.R")
Build functions step-by-step.
Test each line.
Test full function on known inputs.
# Good
checkNames()
calcBA()
# Bad
nameChecker()
baCalculator()
# Variables
names_original
names_checked
tree_dbh
tree_ba
# Good
checkNames <- function(x,
names_correct = 'file-of-correct-names.txt'
) {
# Code of function body goes here, indented
}
# Bad
checkNames <- function(x,
names_correct = 'file-of-correct-names.txt') {
# Here it is hard to tell the arguments from the code body
}
# Good
calcCarbon <- function(dbh, height,
genus = 'Quercus')
# Bad
calcCarbon <- function(dbh, height, genus =
'Quercus')
Each line of comment should begin with a hash and a single space.
# A comment explains why
There are many ways to document your functions.
It should include:
Describe what is returned.
# 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
}