Reputation: 135
I would like to use the accumulate
function with two input vectors and the reduce2
function. The documentation for accumulate
implies that two input vectors can be given and that accumulate
can work with reduce2
. However, I am having trouble.
Here is an example, inspired by the documentation from reduce2
.
This is the example from reduce2
> paste2 <- function(x, y, sep = ".") paste(x, y, sep = sep)
> letters[1:4] %>% reduce2(.y=c("-", ".", "-"), paste2)
[1] "a-b.c-d"
Here are several attempts to use accumulate
similarly to reduce2
. None properly iterate through both letters[1:4]
and c("-",".","-")
.
> letters[1:4] %>% accumulate(.y=c("-", ".", "-"),paste2)
Error in .f(x, y, ...) : unused argument (.y = c("-", ".", "-"))
> letters[1:4] %>% accumulate(c("-", ".", "-"),paste2)
[[1]]
[1] "a"
[[2]]
NULL
> letters[1:4] %>% accumulate(sep=c("-", ".", "-"),paste2)
[1] "a" "a-b" "a-b-c" "a-b-c-d"
How would I use accumulate
to see the intermediate results given by the reduce2
example?
Upvotes: 6
Views: 822
Reputation: 26218
With this trick you can use unlimited arguments in accumulate
and you did not even need accumulate2
library(tidyverse)
x <- letters[1:4]
y <- c('-', '.', '-')
accumulate(seq_along(x[-1]), .init = x[1], ~paste(.x, x[.y+1], sep = y[.y]))
#> [1] "a" "a-b" "a-b.c" "a-b.c-d"
# OR
accumulate(seq_along(y), .init = x[1], ~paste(.x, x[.y+1], sep = y[.y]))
#> [1] "a" "a-b" "a-b.c" "a-b.c-d"
Created on 2022-02-21 by the reprex package (v2.0.1)
Upvotes: 0
Reputation: 4419
A few months after this post accumulate2
was introduced that gives the results OP was after:
library(purrr)
paste2 <- function(x, y, sep = ".") paste(x, y, sep = sep)
accumulate2(letters[1:4], c("-", ".", "-"), paste2)
#> [[1]]
#> [1] "a"
#>
#> [[2]]
#> [1] "a-b"
#>
#> [[3]]
#> [1] "a-b.c"
#>
#> [[4]]
#> [1] "a-b.c-d"
Upvotes: 0
Reputation: 15062
It is possible that this is an oversight where the documentation is simply not up to date/a bit misleading? I could not get accumulate
to accept a three argument function either, and I'm surprised there's no error in your last example though I guess it would have to be paste
that throws it. The fact that the text for .f
is exactly the same for accumulate
as for reduce
makes me think that this just isn't functionality present in accumulate
. Additionally, looking at the source seems to show (unless I misread) that reduce
and reduce2
have their own implementation but accumulate
relies on base::Reduce
. Might be worth a GitHub issue.
Here's my best shot at producing the output you wanted. It basically involves calling reduce2
multiple times with the right subset of the input list and the secondary input vector to paste2
, which doesn't feel very neat or tidy. This might just not be a particularly neat or tidy problem. Note the use of the {}
to override the default %>%
behaviour of placing the pipe LHS as the first argument, and the different indexing on .x
and .y
inside reduce2
(we want to keep .y
one element shorter than .x
).
paste2 <- function(x, y, sep = ".") paste(x, y, sep = sep)
library(purrr)
letters[1:4] %>%
{map_chr(
.x = 2:length(.),
.f = function(index) reduce2(
.x = .[1:index],
.y = c("-", ".", "-")[1:(index - 1)],
.f = paste2
)
)}
#> [1] "a-b" "a-b.c" "a-b.c-d"
Created on 2018-05-11 by the reprex package (v0.2.0).
Upvotes: 1