4  R functions

In R programming, functions are sets of commands that are executed every time the function is called in order to perform a specified task. We have already used some R functions searching for help (e.g., help(), example()).

Most of the computations in R involves using functions. The standard version of R includes a number of built-in functions, and many others can be added or created by the user (user-defined functions).

When we have finished this Chapter, we should be able to:

Learning objectives
  • Understand the concept of functions in R.
  • Know of characteristics of functions.
  • Be familiar with basic mathematical functions (e.g., logarithmic, trigonometric).
  • Create our own functions.

 

4.1 Characteristics of R Functions

A. Name and argumnets of a function

To call a function in R, we simply type its name, followed by open and closing parentheses. Anything we pass to the parentheses separated by a comma are the function’s arguments.

Let’s have look at an example:

seq(from = 5, to = 8, by = 0.5)
[1] 5.0 5.5 6.0 6.5 7.0 7.5 8.0

The function name is seq and we pass three named arguments from = 5, to = 8 and by = 0.5. The arguments from = 5 and to = 8 provide the start and end values of a sequence that we want to create, and by = 0.5 is the increment of the sequence.

The above result can also be obtained without naming the arguments as follows:

seq(5, 8, 0.5)
[1] 5.0 5.5 6.0 6.5 7.0 7.5 8.0
Important

We don’t have to indicate the names of arguments, but only pass the values; R will match the arguments in the order that they appeared (positional matching).

 

Moreover, the seq() function has other arguments1 that we could use and are documented in the help page running ?seq. For example, we could use the argument length.out = 26 (instead of by = 0.5) to create a sequence of 26 numbers as follows:

1 seq(from = 1, to = 1, by = ((to - from)/(length.out - 1)), length.out = NULL, along.with = NULL, …)

NOTE: The numbers inside the brackets, [1] and [16], helps us figure out where in the sequence we are per line. For example, [16] is the id number of the first value (6.80) returned on the second line. Obviously, this number may change depending on the width of the console.
seq(5, 8, length.out = 26)  # 26 numbers in the sequence
 [1] 5.00 5.12 5.24 5.36 5.48 5.60 5.72 5.84 5.96 6.08 6.20 6.32 6.44 6.56 6.68
[16] 6.80 6.92 7.04 7.16 7.28 7.40 7.52 7.64 7.76 7.88 8.00

 

B. Required and optional arguments

And what about this command?

seq(5, 8)
[1] 5 6 7 8

Here, it is assumed that we want a sequence from = 5 that goes to = 8. Since we don’t specify step size, the default value, by = ((to - from)/(length.out - 1)) = (8-5)/(4-1) = 1, is passed to the seq() function.

Some arguments in a function are required while others may be optional.

Now let’s have a look at another example. The log() is a mathematical function that calculates logarithms. We can display the argument names and corresponding default values with the help of the args() function:

args(log)
function (x, base = exp(1)) 
NULL

NOTE: Euler’s Number \(exp(1) ≈ 2.718\)

In the log() function x is a required argument while base is an optional argument and comes with the default value exp(1).

Required argument: Obviously, x is a required argument because if we don’t provide x to the function the calculation will fail (i.e. logarithm is not defined) and we get an error:

log(base=10)

Error: argument x is missing, with no default

Optional argument: If we don’t provide a value for base, R will use the default value exp(1):

log(15)  # R uses the default value of `exp(1)`
[1] 2.70805

But if we pass the argument base = 10 to the function, the base-10 logarithm is calculated:

log(15, base = 10)  # R uses our value 10
[1] 1.176091
Required and optional arguments

For R functions, some arguments must be specified (they are required) and others are optional (because a default value is already given in the definition of the function).

 

We can pass arguments to functions in several ways

Let’s calculate the natural logarithm of 3 (base = \(e\)):

log(3)
[1] 1.098612

Any of the following expressions is equivalent:

log(x=3)
log(x=3, exp(1))
log(x=3, base=exp(1))

log(3, exp(1))
log(3, base=exp(1))

log(base=exp(1), 3)
log(base=exp(1), x=3)
Caution
log(exp(1), 3)

Calculates the logarithm of exp(1) in base 3.

 

Not all functions have (or require) arguments. For example:

[1] "Sun Apr 21 13:58:49 2024"

 

4.2 Mathematical functions

R has many built-in mathematical functions such as the log(x) that we have already seen.

4.2.1 Logarithmic and Exponential functions

 

log(100)     # natural logarithm (or base-e logarithm)
[1] 4.60517
log(0.05)
[1] -2.995732

There are even built-in logarithmic functions with different bases:

log2(100)    # base-2 logarithm
[1] 6.643856
log10(100)   # base-10 logarithm
[1] 2
exp(5)       # exponential exp(1)^5
[1] 148.4132
exp(0.5)     # exponential exp(1)^(1/2)
[1] 1.648721

 

4.2.2 Trigonometric functions (angles in radians)

Trigonometric functions define the relationship among the sides and angles of a right angle triangle. They also allow us to use angle measures, in radians or degrees, to find the coordinates of a point on a circle (e.g., unit circle).

sin(pi/2)  # pi approximately equals to 3.14
[1] 1
cos(pi)
[1] -1
tan(pi/3)
[1] 1.732051

 

4.2.3 Other mathematical functions

sqrt(9)       # returns the squared root of a number
[1] 3
abs(-9)       # returns absolute value of a number
[1] 9
sign(-9)      # returns the sign of a number, -1, 0, or 1
[1] -1
factorial(3)  # factorial 3! = 1x2x3
[1] 6
choose(6, 2)  # number of combinations without replacement 6!/(6-2)!2!
[1] 15

 

4.2.4 The round() function

The round() function is often very useful. The round function follows the rounding principle. By default, we will get the nearest integer. For example:

round(7 / 3)  # rounding 7/3 (2.333) to the nearest integer
[1] 2

If we want to control the approximation accuracy, we can add a digits argument to specify how many digits we want after the decimal point. For example:

round(7 / 3, digits = 2)  # rounding 7/3 to two decimal places
[1] 2.33

 

Round rule when the dropped digit is the number 5

If the first digit that is dropped is exactly 5, R uses a rule that’s common in programming languages: Always round to the nearest even number. For example:

round(1.5)
[1] 2
round(2.5)
[1] 2
round(4.5)
[1] 4
round(5.5)
[1] 6

There are a couple of further relative functions that can be useful in rounding numbers:

ceiling(16.2)       # round to the nearest integer above
[1] 17
floor(16.2)         # round to the nearest integer below
[1] 16
trunc(125.2395)     #  truncates the values in the decimal places
[1] 125
signif (2718214, 3)  # round to the specified number of significant digits
[1] 2720000

4.3 The sessionInfo() and option() functions

We can obtain information about R, our operating system and attached or loaded packages in the current session running the following function:

Additionally, the options() function in R can be used to change various default settings. For example, the digits controls the number of significant digits and the scipen enables/disables scientific notation in printing. The current options are returned when options() is called and the command help(options) lists all of the global options.

help(options)

4.4 User-defined functions

We can create our own functions, using the function(), which is a very powerful way to extend R.

What do we need to create a function?
  1. the function’s name
  2. the arguments of the function
  3. the code of the function (statements)

For example, a simple function that calculates the logarithm of a number to base 7 is following:

log7 <- function(x) {
  log(x, base = 7)
  }

# calculate the logarithm of 5 to base 7
log7(5)
[1] 0.8270875

Here, we defined the function by “assigning” the function(x) to the name log7 using the assignment operator <- (see Chapter 6). The x argument in the parenthesis of function() is used as input to the function; the code within the curly braces {} is the body (statements) of the function.