Encuentra las posiciones iniciales/finales/índices de carreras/valores consecutivos
vector run-length-encoding (2)
Problema: dado un vector atómico, encuentre los índices de inicio y fin de las ejecuciones en el vector.
Vector de ejemplo con carreras:
x = rev(rep(6:10, 1:5))
# [1] 10 10 10 10 10 9 9 9 9 8 8 8 7 7 6
Salida de
rle()
:
rle(x)
# Run Length Encoding
# lengths: int [1:5] 5 4 3 2 1
# values : int [1:5] 10 9 8 7 6
Salida deseada:
# start end
# 1 1 5
# 2 6 9
# 3 10 12
# 4 13 14
# 5 15 15
La clase base
rle
no parece proporcionar esta funcionalidad, pero la clase
Rle
y la función
rle2
sí.
Sin embargo, dado lo pequeña que es la funcionalidad, apegarse a la base R parece más sensato que instalar y cargar paquetes adicionales.
Hay ejemplos de fragmentos de código ( here , here y en SO ) que resuelven el problema ligeramente diferente de encontrar índices de inicio y fin para ejecuciones que satisfacen alguna condición. Quería algo que fuera más general, se pudiera realizar en una línea y no implicara la asignación de variables o valores temporales.
Respondí mi propia pregunta porque estaba frustrado por la falta de resultados de búsqueda. ¡Espero que esto ayude a alguien!
Lógica central:
# 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
way (centrado en el marco de datos):
library(dplyr)
rle(x) %>%
unclass() %>%
as.data.frame() %>%
mutate(end = cumsum(lengths),
start = c(1, dplyr::lag(end)[-1] + 1)) %>%
magrittr::extract(c(1,2,4,3)) # To re-order start before end for display
Debido a que los vectores de
start
y
end
tienen la misma longitud que el componente de
values
del objeto
rle
, resolver el problema relacionado de identificar puntos finales para ejecuciones que cumplan alguna condición es sencillo:
filter
o subconjunte los vectores de
start
y
end
utilizando la condición en los valores de ejecución.
Una posibilidad de
data.table
, donde
.I
y
.N
se utilizan para elegir índices relevantes, por grupo definido por
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