Найти начальную и конечную позиции / индексы прогонов / последовательные значения

Проблема: По атомному вектору найдите начальный и конечный индексы прогонов в векторе.

Пример вектора с прогонами:

x = rev(rep(6:10, 1:5))
# [1] 10 10 10 10 10  9  9  9  9  8  8  8  7  7  6

Выход из rle():

rle(x)
# Run Length Encoding
#  lengths: int [1:5] 5 4 3 2 1
#  values : int [1:5] 10 9 8 7 6

Желаемый результат:

#   start end
# 1     1   5
# 2     6   9
# 3    10  12
# 4    13  14
# 5    15  15

База rle класс, кажется, не обеспечивает эту функциональность, но класс Rle и функция rle2 делать. Однако, учитывая незначительные функциональные возможности, придерживаться базы R кажется более разумным, чем установка и загрузка дополнительных пакетов.

Существуют примеры фрагментов кода ( здесь, здесь и в SO), которые решают несколько иную проблему поиска индексов начала и конца для прогонов, которые удовлетворяют некоторому условию. Я хотел что-то более общее, можно было бы выполнить в одну строку и не включать в себя назначение временных переменных или значений.

Отвечая на мой собственный вопрос, потому что я был разочарован отсутствием результатов поиска. Надеюсь, это кому-нибудь поможет!

1 ответ

Решение

Основная логика:

# Example vector and rle object
x = rev(rep(6:10, 1:5))
rle_x = rle(x)

# Compute endpoints of run
end = cumsum(rle_x$lengths)
start = c(1, lag(end)[-1] + 1)

# Display results
data.frame(start, end)
#   start end
# 1     1   5
# 2     6   9
# 3    10  12
# 4    13  14
# 5    15  15

Tidyverse /dplyr путь (ориентированный на фреймы данных):

library(dplyr)

rle(x) %>%
  unclass() %>%
  as.data.frame() %>%
  mutate(end = cumsum(lengths),
         start = c(1, lag(end)[-1] + 1)) %>%
  extract(c(1,2,4,3)) # To re-order start before end for display

Поскольку start а также end векторы имеют ту же длину, что и values компонент rle Задача, связанная с идентификацией конечных точек для прогонов, удовлетворяющих некоторому условию, проста: filter или подмножество start а также end векторы с использованием условия на значениях прогона.

А data.table возможность, где .I а также .N используются для выбора соответствующих индексов для каждой группы, определенной rleid бежит.

library(data.table)
data.table(x)[ , .(start = .I[1], end = .I[.N]), by = rleid(x)][, rleid := NULL][]
#    start end
# 1:     1   5
# 2:     6   9
# 3:    10  12
# 4:    13  14
# 5:    15  15
Другие вопросы по тегам