8 Function Writing

Writing functions allows us to condense a process into a single function.

8.1 Univariate Case

If we wanted to index a variable by its mean, we could simply type x/mean(x), where x is our vector. However, what if there were a function called index() that makes this process more clear? There is not one inherently in R, but we are able to create it:

index <- function(x) { # the formals/arguments
 
  x/mean(x) # The body
  
}

index(mtcars$mpg)
##  [1] 1.0452636 1.0452636 1.1348577 1.0651734 0.9307824 0.9009177 0.7117748
##  [8] 1.2144968 1.1348577 0.9556696 0.8859854 0.8163011 0.8610981 0.7565718
## [15] 0.5176544 0.5176544 0.7316846 1.6126925 1.5131436 1.6873542 1.0701509
## [22] 0.7715041 0.7565718 0.6620003 0.9556696 1.3588427 1.2941359 1.5131436
## [29] 0.7864365 0.9805569 0.7466169 1.0651734

We can cast this new function over all columns in mtcars with sapply().2

# Get only a few rows.
head(sapply(mtcars, index))
##            mpg       cyl      disp        hp      drat        wt      qsec
## [1,] 1.0452636 0.9696970 0.6934756 0.7498935 1.0843688 0.8143601 0.9221934
## [2,] 1.0452636 0.9696970 0.6934756 0.7498935 1.0843688 0.8936203 0.9535682
## [3,] 1.1348577 0.6464646 0.4680961 0.6340009 1.0704666 0.7211128 1.0426500
## [4,] 1.0651734 0.9696970 1.1182295 0.7498935 0.8563733 0.9993006 1.0891519
## [5,] 0.9307824 1.2929293 1.5603202 1.1930124 0.8758363 1.0692361 0.9535682
## [6,] 0.9009177 0.9696970 0.9752001 0.7158074 0.7673994 1.0754526 1.1328524
##            vs       am      gear      carb
## [1,] 0.000000 2.461538 1.0847458 1.4222222
## [2,] 0.000000 2.461538 1.0847458 1.4222222
## [3,] 2.285714 2.461538 1.0847458 0.3555556
## [4,] 2.285714 0.000000 0.8135593 0.3555556
## [5,] 0.000000 0.000000 0.8135593 0.7111111
## [6,] 2.285714 0.000000 0.8135593 0.3555556

8.2 Multivariate Case

In the univariate case, we indexed a vector by its mean. What if we wanted to use the median instead? We would simply need to replace mean with median. Alternatively, we can add an additional input into our function that specifies what aggregation function to use in the indexing.

index2 <- function(x, f) {
  
  x/f(x)
  
}

Now we can use any function in the f input.

head(index2(mtcars$mpg, mean)) # show only a few elements
## [1] 1.0452636 1.0452636 1.1348577 1.0651734 0.9307824 0.9009177
head(index2(mtcars$mpg, median)) # show only a few elements
## [1] 1.0937500 1.0937500 1.1875000 1.1145833 0.9739583 0.9427083
head(index2(mtcars$mpg, max)) # show only a few elements
## [1] 0.6194690 0.6194690 0.6725664 0.6312684 0.5516224 0.5339233

Our index2 function is actually special in that it is not only a multivariate function but a functional, which is a function that takes another function as an input–see the Functionals chapter for more details.

8.3 Summary

Table 8.1: Summary of Function Writing
Function Description Example
function(x) Write a function, which consists of arguments and the body. index <- function(x) x/mean(x)