ruk·si

# R - Functions

Updated at 2017-10-16 16:54

R has three types of functions:

1. Prefix functions: function name goes before arguments, the most common function type.
2. Inflix functions: function name goes between arguments, all user-created inflix functions must start and end with `%`.
3. Replacement functions: look like prefix functions but with additional assignment `<-` after the function call, modifying the first argument in-place.

Prefix function examples:

``````# Calling a function.
sum(1, 3, 5)
#  9
``````
``````# Function parameters have names which you can use.
rep("Yo ho!", times = 3)
#  "Yo ho!" "Yo ho!" "Yo ho!"
``````

Inflix function example:

```````%+%` <- function(a, b) paste0(a, b)
"new" %+% " string"
#  "new string"
``````

Replacement function examples:

```````second<-` <- function(x, value) {
x <- value
return(x)
}
numbers <- 1:3
second(numbers) <- 5
numbers
#  1 5 3

`modify<-` <- function(x, position, value) {
x[position] <- value
return(x)
}
modify(numbers, 1) <- 10
numbers
#  10  5  3
``````

The most important pre-defined functions:

``````# Open manual page of the function
help(sum)

# Prints usage examples
example(sum)

# Prints argument list and their default values.
formals(MyFunction)
# \$x1
#
# \$x2
#  5

# Prints the function body.
body(MyFunction)
# ...

# Prints the environment where the function is defined.
environment(MyFunction)
# <environment: R_GlobalEnv>
``````

Defining functions:

``````MyFunction <- function(x1, x2 = 5) {
if (missing(x1)) {
return(c(0, 0))
}
z1 <- x1 / x1
z2 <- x2 * x2
myvec <- c(z1, z2)
return(myvec)
}

MyFunction(x1 = 2, x2 = 5)
#   1 25
``````

Name your returns if you return more than one value.

``````DivideAndMultiply <- function(x) {
if (missing(x) ) {
stop("Missing x argument.")
}
if (x < 0) {
warning("You are operating with negative numbers.")
}
x1 <- x / 2
x2 <- x * 2
return(list(divided = x1, multiplied = x2))
}

# DivideAndMultiply()
# Would crash in error because of `stop()`

DivideAndMultiply(-5)
# Warning message:
# In DivideAndMultiply(-5) : You are operating with negative numbers.
# ... but the function will still run and return a value

result = DivideAndMultiply(10)

print(result)
# \$divided
#  5
#
# \$multiplied
#  20

print(result\$divided)
#  5

print(result\$multiplied)
#  20
``````

You can use `...` to take in non-specified amount of arguments.

``````Summy <- function(...) {
arguments <- list(...)
return(arguments)
}
Summy(10, 11, 13)
# []
#  10
#
# []
#  11
#
# []
#  13
``````

You can use `invisble` return so that the result can be assigned but is never printed.

``````Summy <- function(...) {
ellipsis.args <- list(...)
invisible(ellipsis.args)
}
Summy(10, 11, 13)
# ... nothing

# You can force an invisible value to be displayed by wrapping it.
a <- 2
# ... nothing
(a <- 2)
#  2
``````

Use `do.call` to call a function with a list of arguments.

``````arguments <- list(1:10, na.rm = TRUE)
do.call(mean, arguments)
#  5.5
``````

`%>%` pipe operator is not part of base R, it's defined by `magrittr` package. Good to understand how it works as it's quite common, basically it sends the left hand side as the first argument to the right hand side.

``````library(magrittr)