7

I would like to find contiguous runs of non-zero elements in a vector (separated by at least one zero), and to assign an ID to each group (subsequent integer).

Toy vector:

value <- c(1, 1, 2, 3, 4, 3, 0, 0, 0, 1, 2, 3, 9, 8, 0, 0, 3, 2)

In this example, there are three runs of non-zero values: [1,1,2,3,4,3], [1,2,3,9,8], [3,2], separated by chunks of one or more zeros.

Each non-zero run should have a unique ID: 1, 2, 3... Runs of zero should have NA as ID:

   value id
1      1  1
2      1  1
3      2  1
4      3  1
5      4  1
6      3  1
7      0 NA
8      0 NA
9      0 NA
10     1  2
11     2  2
12     3  2
13     9  2
14     8  2
15     0 NA
16     0 NA
17     3  3
18     2  3
Henrik
  • 61,039
  • 13
  • 131
  • 152
quarandoo
  • 339
  • 2
  • 8

5 Answers5

12

You can try:

as.integer(factor(cumsum(value==0)*NA^(value==0)))
#[1]  1  1  1  1  1  1 NA NA NA  2  2  2  2  2 NA NA  3  3
nicola
  • 23,063
  • 3
  • 31
  • 52
7

Using rle(). First create a new vector replacing the zeros with NA.

x <- match(value != 0, TRUE)
with(rle(!is.na(x)), {
    lv <- lengths[values]
    replace(x, !is.na(x), rep(seq_along(lv), lv))
})
# [1]  1  1  1  1  1  1 NA NA NA  2  2  2  2  2 NA NA  3  3
Rich Scriven
  • 93,629
  • 10
  • 165
  • 233
2

You could also do this:

id <- (value>0)^NA
x <- rle(value>0)$lengths[c(TRUE, FALSE)]
id[!is.na(id)] <- rep(seq_along(x), times=x)

#[1]  1  1  1  1  1  1 NA NA NA  2  2  2  2  2 NA NA  3  3
989
  • 11,865
  • 5
  • 27
  • 49
1

Another possibility:

ifelse(value != 0, 
       cumsum(value != 0 & dplyr::lag(value) %in% c(0, NA)), 
       NA)

# [1]  1  1  1  1  1  1 NA NA NA  2  2  2  2  2 NA NA  3  3
Scarabee
  • 5,267
  • 5
  • 26
  • 51
-2
  1. You need to define a vector of vectors so in v[0] you will find all values of the first group, and in v[1] you will find all values of the second group and so on,
  2. You need to loop on all values when you find a zero value. Continue until you find anon zero. Increment the vector with one and add the value and so on,

I wish this answer be helpful.

Peter Mortensen
  • 30,030
  • 21
  • 100
  • 124
khaled
  • 1
  • 1