In R, functions are another type of object. We use functions to perform a task repeatedly or in different settings; functions are there to make our code more efficient. We can use built in R functions (we’ve used several already!) or create our own.

The Anatomy of an R Function

The general template for a function call is

function_name(arg1, arg2, ...)

where

Building a Function

The general template for building a function is

function_name <- function(arg1 = default, arg2, ...){
  # Function body
  ...
  return(return_value)
}

where

A Simple Function

# Convert temperature from Fahrenheit (F) to Celsius (C)
# ARGUMENTS: temp_F, a numeric vector in F units
# RETURNS:   temp_C, a numeric vector (of the same length as temp_F) in C units
f2c <- function(temp_F){
  temp_C <- (temp_F - 32) * 5 / 9
  return(temp_C)
}

f2c(temp_F = 100) # convert 100 degrees F to degrees C
## [1] 37.77778

We can also call a function without using the names of the arguments. We just need to make sure we put the arguments into the function call in order.

f2c(100)
## [1] 37.77778

If we try to call a function without necessary arguments, we get an error

f2c()

Sometimes, we may want to avoid this by including default arguments.

# An example function, does simply algebra 
# ARGUMENTS: a = 1 (default), a numeric vector of length 1 
#            b, a numeric vector of length 1
# RETURNS:   d, a numeric vector of length 1
example_func <- function(a = 1, b){
  c = a + b
  d = c + 1
  
  # returns a+b+1
  return(d)
}

# Call example function
example_func(a = 2,  b= 3)
## [1] 6
# or
example_func(2, 3) # in order!
## [1] 6

Since this function is written with a default value for \(a\), we can also run it without providing any a:

example_func(b=2) 
## [1] 4

In this case, we do need to specify b=, because including arguments in order means that if we only wrote example_func(2), R would assume that a=2 and wouldn’t know what to do about b (since it doesn’t have a default)!

By convention, most R functions are built with this in mind, so arguments with defaults are placed toward the end.

Live Example

Let’s build a function in class.

On Your Own

Write a function named func that takes in argument x, which has default value 0. The function should calculate x+4 and return the answer. Test your function with x=3.

Lexical Scoping

What? Basically, the stuff that happens in the function doesn’t get stored in the global environment. This helps keep R tidy. This is mostly something to keep in mind as you work on troubleshooting your code!

Sometimes you may have an object defined in multiple places. When this happens, R uses a system of rules to determine which definition it will use. In other words, how and where we define an object determines the objects scope, or range of places that we can use this object. The system of rules R uses for searching for objects is called lexical scoping, as opposed to other types of scoping. With this system R looks for objects that are called in a function within the itself, then any enclosing environments, then the global environment, and lastly looking at objects in packages or built-in objects. This is the same searching method that we see in Python and Java.

Built-In Functions

We’ve actually already seen a lot of built-in R functions!

and others!

Let’s use the built-in dataset mtcars and calculate the mean, median, variance, standard deviation, square root, range, and summary of the mpg variable.

Help Files

?rep
## starting httpd help server ... done

On Your Own

Run the following code chunk:

v1 <- c(1,4,7,2, NA)
mean(v1)
## [1] NA

Examine the help file for mean. How can we get the function to give us a mean for v1 (without returning NA)? Change the code chunk above to do this.