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)
# [1] 9
# Function parameters have names which you can use.
rep("Yo ho!", times = 3)
# [1] "Yo ho!" "Yo ho!" "Yo ho!"

Inflix function example:

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

Replacement function examples:

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

`modify<-` <- function(x, position, value) {
  x[position] <- value
  return(x)
}
modify(numbers, 1) <- 10
numbers
# [1] 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
# [1] 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]  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
# [1] 5
#
# $multiplied
# [1] 20

print(result$divided)
# [1] 5

print(result$multiplied)
# [1] 20

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

Summy <- function(...) {
    arguments <- list(...)
    return(arguments)
}
Summy(10, 11, 13)
# [[1]]
# [1] 10
#
# [[2]]
# [1] 11
#
# [[3]]
# [1] 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)
# [1] 2

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

arguments <- list(1:10, na.rm = TRUE)
do.call(mean, arguments)
# [1] 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)
cars %>% head()
#   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1          5.1         3.5          1.4         0.2  setosa
# 2          4.9         3.0          1.4         0.2  setosa
# 3          4.7         3.2          1.3         0.2  setosa
# 4          4.6         3.1          1.5         0.2  setosa
# 5          5.0         3.6          1.4         0.2  setosa
# 6          5.4         3.9          1.7         0.4  setosa

Sources

  • Google Developers R Programming Videos
  • Try R