2

I have the following simple vector:

a = c(1,0,0,1,0,0,0,0)

and I would like to obtain a vector (b) such that for each indicator x in a, if a[x] is 1, we let it as is, and if it is 0, we compute a[x-1] + 1, until the next 1:

b = c(1,2,3,1,2,3,4,5) 

I tried using map():

map(
  .x = seq(1,(length(a))),
  .f = function(x) {
    a[x] = ifelse(a[x]==1, a[x], a[x-1]+1)
    a})

Obviously this does not work because map does not update the a vector. How can I do this using map(). Is it even possible to update a something outside map() ?

1
  • My solution to your previous question, uses purrr::reduce, which may correspond to what you are looking for. Commented May 2, 2022 at 11:15

2 Answers 2

2

If you just change it to use the superassignment operator <<-, the way you attempted it does in fact work.

a = c(1,0,0,1,0,0,0,0)

map(
  .x = seq(1,(length(a))),
  .f = function(x) {
    a[x] <<- ifelse(a[x]==1, a[x], a[x-1]+1)
    a})
a

#> [1] 1 2 3 1 2 3 4 5
Sign up to request clarification or add additional context in comments.

2 Comments

Could you explain a little bit more what the superassignment does?
It's actually called 'scoping assignment' if you wanna make research yourself
1

Maybe a solution close to what you're looking (i.e. that would mimic a for loop) for is purrr::accumulate.

accumulate(1:8, .f = ~ ifelse(a[.y] == 1, 1, .x + 1))
#[1] 1 2 3 1 2 3 4 5

3 Comments

I did not know the accumulate function, very nice. Yet I think the conceptual question remains: how can I update an outside object in map?
Can you explaine what is the .y argument? from ?accumulate i see only .x
This is indeed not well documented: .y is the value in the list, .x is the previous value. See here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.