Получить начальный и конечный диапазоны из последовательности, содержащей пробелы

avatar
Kalaschnik
8 августа 2021 в 15:47
47
2
4

Предположим, у меня есть следующие данные:

c(1:4,7:15,20:23,25,30:35,40,41)

Я хочу получить начальный и конечный диапазоны этого вектора. Тем не менее, я хочу пропустить отдельные значения, у которых нет естественного предшественника и преемника (в примере: 25). Другими словами, для создания «диапазона» должно быть как минимум два последовательных значения.

Начальные диапазоны в этом примере: 1, 7, 20, 30, 40 Их соответствующие конечные диапазоны: 4, 15, 23, 35, 41

Есть ли элегантное встроенное решение? Я практически застрял в аду цикла for.

Источник

Ответы (2)

avatar
Ben Bolker
8 августа 2021 в 15:55
3

Определите места, где diff(x) > 1, с соответствующей задержкой, добавив TRUE в начало или конец последовательности. (diff(x) создает вектор, который на один элемент короче, чем x.) Предложения & избавляются от одноэлементных значений.

dx1 <- c(TRUE,diff(x)>1)
dx2 <- c(diff(x)>1, TRUE)
start <- x[dx1 & !dx2]
end <-   x[dx2 & !dx1]

Возможно, также существует решение с чем-то вроде rle(diff(x)==1), но оно будет немного сложнее, чем приведенное выше решение (может быть полезно, если, например, вы хотите идентифицировать прогоны определенной длины).

Kalaschnik
8 августа 2021 в 16:01
0

О мой Бог! Вы уложили это в 4 строчки кода... Большое спасибо!

avatar
tmfmnk
8 августа 2021 в 16:29
0

Мало что добавляет к решению @Ben Bolker, но может быть и другой способ:

ind <- aggregate(x ~ cumsum(c(FALSE, diff(x)) > 1), FUN = function(x) (length(x) > 1) * range(x))
ind$x[ind$x[, 1] != 0, ]

     [,1] [,2]
[1,]    1    4
[2,]    7   15
[3,]   20   23
[4,]   30   35
[5,]   40   41