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
  • 65,555
  • 14
  • 143
  • 159
quarandoo
  • 369
  • 4
  • 9

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
  • 24,005
  • 3
  • 35
  • 56
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
  • 97,041
  • 11
  • 181
  • 245
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
  • 12,579
  • 5
  • 31
  • 53
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,437
  • 5
  • 29
  • 55
-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,738
  • 21
  • 105
  • 131
khaled
  • 1
  • 1