Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find consecutive values in vector in R [duplicate]

Tags:

r

If I have a vector as such:

dat <- c(1,2,3,4,5,19,20,21,56,80,81,92)

How can I break it up into a list as:

[[1]]
1 2 3 4 5

[[2]]
19 20 21

[[3]]
56

[[4]]
80 81

[[5]]
92
like image 741
user41912 Avatar asked Jul 19 '14 06:07

user41912


2 Answers

Just use split in conjunction with diff:

> split(dat, cumsum(c(1, diff(dat) != 1)))
$`1`
[1] 1 2 3 4 5

$`2`
[1] 19 20 21

$`3`
[1] 56

$`4`
[1] 80 81

$`5`
[1] 92

Not exactly what you asked for, but the "R.utils" package has a couple of related fun functions:

library(R.utils)
seqToIntervals(dat)
#      from to
# [1,]    1  5
# [2,]   19 21
# [3,]   56 56
# [4,]   80 81
# [5,]   92 92
seqToHumanReadable(dat)
# [1] "1-5, 19-21, 56, 80-81, 92"
like image 50
A5C1D2H2I1M1N2O1R2T1 Avatar answered Nov 01 '22 04:11

A5C1D2H2I1M1N2O1R2T1


I think Robert Krzyzanowski is correct. So here is a tidyverse that involves placing the vector into a tibble (data frame).

library(tidyverse)
# library(dplyr)
# library(tidyr)

df <- c(1,2,3,4,5,19,20,21,56,80,81,92) %>%
  tibble(dat = .)

# using lag()
df %>%
  group_by(seq_id = cumsum(dat != lag(dat) + 1 | is.na(dat != lag(dat) + 1)) %>%
  nest()

# using diff()
df %>%
  group_by(seq_id = cumsum(c(1, diff(dat)) != 1)) %>%
  nest()

Of course, you need not nest the resulting groups into list-columns, and can instead perform some kind of summary operation.

like image 37
seasmith Avatar answered Nov 01 '22 04:11

seasmith