Chapter 13 Functions

This chapter contains the basics of how to write a function, links to more complete instructions, and examples of functions.

13.1 User defined functions (UDFs)

A non-exhaustive list of possible reasons for writing your own functions;

  • you are repeating some code chunk changing only a few variables each time.
  • you want to apply the same set of commands to multiple instances of some object: it might be a dataframe, a text string, a document, an image etc.
  • tidier code, you can write the functions in a separate R file and load these functions by running that file when you load other packages.
  • easier to update, just update the function rather than edit potentially multiple code chunks.
  • prevents copy/paste errors
  • you are writing a package/library

13.2 Top tips for writing functions

  • name the function something sensible that gives you a clue what it does, usually containing a verb, and making sure that it doesn’t conflict with names of other functions in use.
  • write some description of what the function is intended for and the expected outcome, including what it needs to work properly, eg it might take an integer value argument only, and therefore fail if given a double.
  • make your function as independent as possible, use name_space::function syntax if it uses functions from other packages so they don’t have to be loaded (they will have to be installed though).
  • recommend passing named arguments rather than relying on global variables (again name your arguments clearly).
  • recommend giving arguments default values, this shows an example of the type of variable that is expected here.
  • note that variables assigned inside a function will not appear in the global environment unless explicitly returned.
  • using an explicit return statement is useful if the function is complex, otherwise the output will be the final evaluated expression.

13.3 Function structure

Below is an example of the syntax for defining a function named state_animal_age. The list of named arguments are included in brackets () with defaults. The function code sits inside braces {}, and returns a single string of the concatenated inputs.

state_animal_age <- function(animal = "animal type", age = 0) {
  #function takes animal name as a string and current age and pastes them together
  #output is single string
  return( paste(animal, age, sep = ': ') )
}

#run function with defaults
state_animal_age()
#> [1] "animal type: 0"

#run function passing inputs to argument names, order doesn't matter
state_animal_age(age = 2, animal = "potoo")
#> [1] "potoo: 2"

#run function passing inputs by position, order matters
state_animal_age("tortoise", 169)
#> [1] "tortoise: 169"

13.4 Function with purrr structure

The scenario in which I most find myself writing functions is when I want to do the same thing to a set of similar objects. I write a function that does what I want to one object and then use purrr::map (or one of its siblings) to iterate through the complete list of objects. This greatly simplifies the entire process. For examples see Chapter 3 .xlsx and .xls section and below.

Using the function above that takes two inputs I can use purrr::map2 to iterate over two lists of these input values. Note that the corresponding values in each list form a pair of inputs for the function, so we get three outputs. Consider how this is different to iterating over nested lists, where, in this case, we would get nine outputs.

animal_list = c('cat', 'dog', 'elephant')
age_list = c(12, 7, 42)

purrr::map2(.x = animal_list, .y = age_list, .f = state_animal_age)
#> [[1]]
#> [1] "cat: 12"
#> 
#> [[2]]
#> [1] "dog: 7"
#> 
#> [[3]]
#> [1] "elephant: 42"

13.5 Packages within DfT

In addition to writing your own functions, there are a number of packages available for you to use in DfT. As good practice, you should always aim to use an existing package when one is available rather than writing your own functions, as this ensures your code remains maintained and consistent.

DfT packages currently available include:

  • dftplotR Create charts with accessible DfT-themed formatting and colour palettes
  • slidepackR Create DfT-themed HTML slidepacks in R
  • tableformatR Format openxlsx tables to make them accessible for publication
  • mojspeakr Technically not a DfT package, but widely used here! Helps to convert Rmarkdown to a format suitable for publication on gov.uk