Найти начальную и конечную позиции / индексы прогонов / последовательные значения
Проблема: По атомному вектору найдите начальный и конечный индексы прогонов в векторе.
Пример вектора с прогонами:
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