Creating a set of indicators based on the sequential occurrence of a number in a vector of integers

Viewed 46

Let's say that I have a vector of integers

x <- c(10, 1, 1, 4, 10, 10, 7, 7, 7)

and I want to create two sets of indicators based on this vector. The first indicator , y, should be equal to 1 as long as x == 10 and then equal to zero for the rest of the vector. Importantly, it has to ignore any additional 10 found later in the vector. For example, given x above, I would expect

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

and if

x <- c(10, 10, 10, 1, 1, 5, 10, 7, 9)

then

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

The second indicator, z should be equal to 1 for the first element after the sequence has ended. Given the x vectors above, I would expect the outputs to be:

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

Using one vector to work out the other is perfectly fine. I haven't been able to find a neat way of solving this given that the number used to work out the sequence can occur later in the vector, so a simple check for equality doesn't work in my case.

1 Answers

We could use rle to change the values that are not equal to the first set of 10 to 0 by assigning those 'values' to FALSE

+(inverse.rle(within.list(rle(x == 10), values[seq_along(values) > 1] <- FALSE)))
#[1] 1 0 0 0 0 0 0 0 0
+(inverse.rle(within.list(rle(x == 10), values[seq_along(values) > 1] <- FALSE)))
#[1] 1 1 1 0 0 0 0 0 0

for the second case, get the position with which and create a logical vector with %in%

library(data.table)
+( seq_along(x) %in% which(rleid(x == 10) > 1)[1])
#[1] 0 1 0 0 0 0 0 0 0

 +( seq_along(x) %in% which(rleid(x == 10) > 1)[1])
#[1] 0 0 0 1 0 0 0 0 0
Related