4

Suppose we have a vector:

v <- c(0,0,0,1,0,0,0,1,1,1,0,0)

Expected output:

v_index <- c(5,6,7)

v always starts and ends with 0. There is only one possibility of having cluster of zeros between two 1s.

Seems simple enough, can't get my head around...

zx8754
  • 52,746
  • 12
  • 114
  • 209

3 Answers3

9

I think this will do

which(cumsum(v == 1L) == 1L)[-1L]
## [1] 5 6 7

The idea here is to separate all the instances of "one"s to groups and select the first group while removing the occurrence of the "one" at the beginning (because you only want the zeroes).

David Arenburg
  • 91,361
  • 17
  • 137
  • 196
  • 2
    `1L` is class of integer and `1` is class of numeric. Any reason to use `1L` instead of just `1`? – zx8754 Apr 01 '15 at 21:43
  • 2
    There is no particular reason. I think it is a bit faster and I was under the impression that you are dealing with integers here (though `typeof(v)` returns `double`). There are some discussions about this [here](http://stackoverflow.com/questions/22191324/clarification-of-l-in-r/), [here](http://stackoverflow.com/questions/24350733/why-would-r-use-the-l-suffix-to-denote-an-integer) and [here](http://cran.r-project.org/doc/manuals/r-release/R-lang.html#Constants). In your case your can survive without the `L` too. – David Arenburg Apr 01 '15 at 21:51
4
v <- c(0,0,0,1,0,0,0,1,1,1,0,0)
v_index<-seq(which(v!=0)[1]+1,which(v!=0)[2]-1,1)


> v_index
[1] 5 6 7

Explanation:I ask which indices are not equal to 0:

which(v!=0)

then I take the first and second index from that vector and create a sequence out of it.

maRtin
  • 6,336
  • 11
  • 43
  • 66
4

This is probably one of the simplest answers out there. Find which items are equal to one, then produce a sequence using the first two indexes, incrementing the first and decrementing the other.

block <- which(v == 1)
start <- block[1] + 1
end <- block[2] - 1
v_index <- start:end
v_index
[1] 5 6 7
codingEnthusiast
  • 3,800
  • 2
  • 25
  • 37