3

I have the following list of numeric values in R:

sales_by_hour = c(130, 21, 0, 0, 0, 0, 6, 244, 391, 408, 431, 0, 0, 471, 
                  530, 573, 643, 643, 667, 787, 990, 1024, 1012, 712)

Then I have applied the following code to obtain the indexes of the min values

which(test2==0)

which returns the values c(3,4,5,6,12,13). However I would like to then split again this list in 2 or more lists ex. c(3,4,5,6) and c(12,13), since I want to separate non consecutive series of number.

M--
  • 25,431
  • 8
  • 61
  • 93
Oliver
  • 443
  • 4
  • 10
  • ```split(which(sales_by_hour==0), cumsum(c(1, diff(which(sales_by_hour==0)) != 1)))``` – M-- Aug 13 '19 at 17:24
  • Related: [How to find the indices where there are n consecutive zeroes in a row](https://stackoverflow.com/questions/50311720/how-to-find-the-indices-where-there-are-n-consecutive-zeroes-in-a-row/) – IceCreamToucan Aug 13 '19 at 17:52

2 Answers2

3

It can be done in base:

split(which(sales_by_hour==0), cumsum(c(1, diff(which(sales_by_hour==0)) != 1)))

#> $`1`
#> [1] 3 4 5 6
#> 
#> $`2`
#> [1] 12 13
M--
  • 25,431
  • 8
  • 61
  • 93
1

1) rleid Using the input in the Note at the end, we can use rleid from data.table. It assigns a unique number to each run in the input resulting in a compact solution.

library(data.table)
split(seq_along(x)[x == 0], rleid(x)[x == 0])

giving:

$`3`
[1] 3 4 5 6

$`9`
[1] 12 13

2) Base R This could also be done in base at the expense of a slightly longer solution. Here the value of inverse.rle(r) is the same as the value of rleid(x) and is done without using any packages.

r <- rle(x)
r$values <- seq_along(r$values)
split(seq_along(x)[x == 0], inverse.rle(r)[x == 0])

Note

The input in reproducible form:

Line <- "130   21    0    0    0    0    6  244  391  408  431  0  0  471  530  573  643  643  667  787  990 1024 1012  712"
x <- scan(text = Line)
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341