user189035 - 7 months ago 24
R Question

# Increment values in vector conditionally (conditional restarting running sum)-- vectorized version?

Given a vector of binary values

`out_2`
the code below returns a vector
of same length as
`out_2`
called
`out_1`
.
The entries of
`out_1`
counts the number of successive similar items left in
`out_2`
before the next sign switch. If you print the final
`cbind()`
I think you will see what I mean.

``````  library(zoo)
n = 10
out_2 = rep(NA, n)
out_2[sample.int(n, 3)] = sample(c(-1, 1), 3, replace = TRUE)
out_2 = zoo::na.locf(out_2)
out_1 = out_2
out_1[length(out_2)] = 1
for(i in (length(out_2) - 1):1){
out_1[i] = ifelse(out_2[i + 1] == out_2[i], out_1[i + 1] + 1, 1)
}
cbind(out_1, out_2)
``````

I was wondering if there is a one liner vectorized way to get
`out_1`
from
`out_2`
(i.e. vectoring the explicit for loop)?

I would use `rle` from base `R`. The tricky part is to get the reverse order for the `out_1` vector, so it has (?) to go through `lapply'

``````out_1<- unlist(lapply(rle(out_2)\$lengths, function(x) seq(x, by=-1)))
``````

And the result is:

``````cbind(out_1, out_2)
out_1 out_2
[1,]     2    -1
[2,]     1    -1
[3,]     1     1
[4,]     6    -1
[5,]     5    -1
[6,]     4    -1
[7,]     3    -1
[8,]     2    -1
[9,]     1    -1
``````

If you're flexible with the output and you don't need it to be in reverse order, you can simply use the `sequence` function.

``````out_1<- sequence(rle(out_2)\$lengths)
cbind(out_1, out_2)
out_1 out_2
[1,]     1    -1
[2,]     2    -1
[3,]     1     1
[4,]     1    -1
[5,]     2    -1
[6,]     3    -1
[7,]     4    -1
[8,]     5    -1
[9,]     6    -1
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download