<- c("first" = 1L, "second" = 2L, "third" = 3L, "fourth" = 4L)
my_vec ::construct(my_vec) constructive
c(first = 1L, second = 2L, third = 3L, fourth = 4L)
Layal Christine Lettry
cynkra GmbH
University of Fribourg, Dept. of Informatics, ASAM Group
September 9, 2024
What functions can you use to replace a loop?
Let’s assume that we have a numeric vector.
reduce()
from purrrLet’s say we want to compute the sum and the product of all the elements of our vector. We can use the reduce()
function.
It is the same as doing
We could also write a loop for the sum, which would perform exactly the same operations as reduce()
, but in a more complicated way.
# Define the function f
f <- function(x, y) {
x + y
}
# Start with the first value
my_vec <- unname(my_vec)
result <- my_vec[1]
# Loop through the rest of the values
for (i in 2:length(my_vec)) {
result <- f(result, my_vec[i])
}
print(result)
[1] 10
These results show that reduce()
takes the vector values and applies the +
or *
function iteratively in the forward
direction (default).
Let the function f
be defined by f(a, b) = a + b
. Then, reduce()
will apply this to my_vec
, i.e.
\[ f(f(f(1, 2), 3), 4) = f(f(3, 3), 4) = f(6, 4) = 10. \]
If the direction had been set backwards
, the following would have occurred:
\[ f(f(f(4, 3), 2), 1) = f(f(7, 2), 1) = f(9, 1) = 10. \]
To see the difference between forward
and backward
, let’s subtract the elements of our vector iteratively.
Let the function g
be defined by g(a, b) = a - b
. Then, the forward
subtraction corresponds to this operation:
\[ g(g(g(1, 2), 3), 4) = g(g(-1, 3), 4) = g(-4, 4) = -8. \]
The the backward
subtraction would be:
\[ g(g(g(4, 3), 2), 1) = g(g(1, 2), 1) = g(-1, 1) = -2. \]
We could set the initial value of the accumulation.
Here, there is one additional argument and the iteration starts with the value of 3
that corresponds to my_vec[[3]]
:
\[ g(g(g(g(3, 1), 2), 3), 4) = g(g(g(2, 2), 3), 4) = g(g(0, 3), 4) = g(-3, 4) = -7. \]
Let’s say we want to compute the empiric variance for our vector.
We usually compute it with var(my_vec) =
1.6666667. This is an unbiased estimator of the variance because the denominator is n-1 = length(my_vec) - 1 =
3. The following operation:
corresponds to
\[
1/(n-1) \sum_{i = 1}^n (x_i - \bar{x})^2.
\] However, it does not work when we try to apply this formula using reduce()
, because we need to supply two arguments.
Error in fn(out, elt, ...): unused argument (elt)
Let’s do it by entering two arguments into the reduce()
function.
[1] 0.3828125
# or
my_var <- function(x, y) {
1 / (length(c(x, y)) - 1) * sum((c(x, y) - mean(c(x, y)))^2)
}
my_vec |>
purrr::reduce(\(x, y) my_var(x, y))
[1] 0.3828125
So, what does reduce()
compute?
Let \(x =\) my_vec
and \(h(x_1, x_2)\) be a function defined by
\[
h(x_1, x_2) = var(x_1, x_2) = 1/(2-1) \sum_{i = 1}^2 (x_i - \bar{x})^2 = \left[x_1 - \frac{(x_1 + x_2)}{2}\right]^2 + \left[x_2 - \frac{(x_1 + x_2)}{2}\right]^2.
\] Thus, we get 0.3828125 because reduce()
computes \(h(h(h(1, 2), 3), 4)\) which is equal to
If .init
is not specified, the function reduce2()
takes as arguments a first vector and a second one which is shorter than the former by one element. Otherwise, both arguments should have the same number of of elements.
[1] "5 1 1 2 2 3 3 4 4"
[1] "1 2 7 3 8 4 9"
If .init
is not specified, the reduce2()
function takes as the initial value the first element of the first argument.
Otherwise, the argument .init
gives the first element. This is the first argument.
Then, the values going from the first non-used element of the two arguments (here my_x
and my_y
) will be the second and the third elements.
accumulate()
from purrrThe function accumulate()
will give the intermediate results of the reduce()
function.
[1] 1 3 6 10
[1] 1 2 6 24
[1] 1.0000000 0.5000000 3.1250000 0.3828125
You can alsow use accumulate2()
if you use 2 lists.
[[1]]
[1] 5
[[2]]
[1] "5 1 1"
[[3]]
[1] "5 1 1 2 2"
[[4]]
[1] "5 1 1 2 2 3 3"
[[5]]
[1] "5 1 1 2 2 3 3 4 4"
[[1]]
[1] 1
[[2]]
[1] "1 2 7"
[[3]]
[1] "1 2 7 3 8"
[[4]]
[1] "1 2 7 3 8 4 9"
@online{lettry2024,
author = {Lettry, Layal Christine},
title = {How Do You Iterate a Vector?},
date = {2024-09-09},
url = {https://rdiscovery.netlify.app/posts/2024-09-09_reduce/},
langid = {en}
}