Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract consecutive sequences from vector

Tags:

r

sequence

I have a vector called v with positive and negative values as well as zeros. The question is, how to extract (in a list) all the continuous sequences of positive numbers, that is the sequences of positive numbers separated by zeros.

Here is v:

v <- c(-75.09619, -38.31229,   0,  57.17792,  65.55923, 108.52735, 104.29929,  32.47125,0,   0,   0,   0, -26.65008, -49.48638, -79.60670,-90.55343, -34.60761,   0, 21.48842, 38.83820, 42.28727, 0)

The output must be something like:

[1] 57.17792,  65.55923, 108.52735, 104.29929,  32.47125
[2] 21.48842 , 38.83820, 42.28727

Any ideas?

like image 372
WAF Avatar asked Jan 13 '15 23:01

WAF


2 Answers

Here's a short one using split:

split(v[v>0],cumsum(v==0)[v>0])
#$`1`
#[1]  57.17792  65.55923 108.52735 104.29929  32.47125
#
#$`6`
#[1] 21.48842 38.83820 42.28727

This essentially just subsets v to positive numbers, then uses the cumsum(v==0) counter (which will be stable within a group of positive values, and increase when it hits the immediately following 0), to split this group. Voila!


Another attempt using rle:

r <- rle(v>0)
start <- cumsum(r$lengths)[r$values] - r$lengths[r$values] + 1
end <- start + r$lengths[r$values] - 1
Map(function(start,end) v[start:end],start,end)

#[[1]]
#[1]  57.17792  65.55923 108.52735 104.29929  32.47125
#
#[[2]]
#[1] 21.48842 38.83820 42.28727
like image 129
thelatemail Avatar answered Oct 13 '22 20:10

thelatemail


You can try:

indices <- which(v[v>=0]==0)
x <- Map(function(x,y) setdiff(v[v>=0][(y+1):(x-1)],0),
         indices[2:length(indices)],
         indices[1:(length(indices)-1)])
x[vapply(x,length,1L)>0]
#[[1]]
#[1]  57.17792  65.55923 108.52735 104.29929  32.47125
#[[2]]
#[1] 21.48842 38.83820 42.28727

What I did:

  • took the 0 position out of the vector formed with the >=0 values of v
  • with the Map function, you can extract the part of the vector between two zeros
  • the last line's purpose is to strip from the result the sequences without values (if for instance there are sequences of two or more zeroes in the original vector)
like image 7
nicola Avatar answered Oct 13 '22 21:10

nicola