```
<- c("first" = 1L, "second" = 2L, "third" = 3L, "fourth" = 4L)
my_vec ::construct(my_vec) constructive
```

`c(first = 1L, second = 2L, third = 3L, fourth = 4L)`

purrr

constructive

reduce

accumulate

loop

iteration

Author

Affiliations

Layal Christine Lettry

cynkra GmbH

University of Fribourg, Dept. of Informatics, ASAM Group

Published

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"
```

BibTeX citation:

```
@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}
}
```

For attribution, please cite this work as:

Lettry, Layal Christine. 2024. “How Do You Iterate a
Vector?” September 9, 2024. https://rdiscovery.netlify.app/posts/2024-09-09_reduce/.