This is a big concept in R. To help make sense of the possibilities, it can be useful to consider the dimensionality of the input(s) and output of the various functions.
We already saw functions that take in a vector and return a single, scalar-like value:
v <- 1:5
length(v)
#> [1] 5
sum(v)
#> [1] 15
Many statistical functions are also in this category, such as mean().
For logical vectors, there are all() and any(), which return a single TRUE or FALSE.
Many functions in R will operate on entire vectors, often giving vector output. This includes most of the mathematical functions:
sq <- c(4, 9, 16, 25)
sqrt(sq) # square root
#> [1] 2 3 4 5
This is not just concise and convenient, avoiding the need for loops, list comprehensions or recursion which are common in other languages. In R, vector functions often run much faster than those techniques.
You already used vectorized functions more than you probably realized. Compare these:
v <- c(2, 7, 9)
w <- c(3, 1, 5)
v + w
#> [1] 5 8 14
"+"(v, w)
#> [1] 5 8 14
The familiar infix operators are just syntactic sugar for the underlying vectorized function! In this case "+"().
For sorting a vector, there is sort() to return the values and order() to return the indices:
v <- c("I", "am", "not", "in", "order")
sort(v)
#> [1] "am" "I" "in" "not" "order"
order(v)
#> [1] 2 1 4 3 5
The default is to sort in ascending order.
Specify decreasing = TRUE if necessary, or use rev() to reverse an existing vector.
v <- c("I", "am", "not", "in", "order")
sort(v, decreasing = TRUE)
#> [1] "order" "not" "in" "I" "am"
rev(1:4)
#> [1] 4 3 2 1
There are also functions such as cumsum() and cumprod() to produce cumulative vector outputs, operating on the input vector left-to-right:
cumsum(1:5)
#> [1] 1 3 6 10 15 # sums
cumprod(1:5)
#> [1] 1 2 6 24 120 # equivalent to factorials
The above examples are similar to foldl operations in many functional languages, except that the output is a vector with all the intermediate values.
An extension of this concept can also be used to compare vectors.
For example, consider the pairwise-max function pmax():
v
#> [1] 2 7 9
w
#> [1] 3 1 5
pmax(v, w)
#> [1] 3 7 9 # max of each pairwise comparison
This function and others like it also accept an arbitrary number of input vectors, not just two.
The above example uses vectors of equal length. As discussed in the Vector Filtering Concept, R uses recycling to extend vectors which are somehow "too short". To repeat: use this with care, and preferably only with a length-1 vector.
pmax(v, 5)
#> [1] 5 7 9
This is less common, but it is fairly easy to write functions that are apparently scalar-in, vector out.
When applied to vector input, the output is a 2-D matrix (covered in a later concept).