Buscar..


Observaciones

Una carrera es una secuencia consecutiva de valores u observaciones repetidas. Para valores repetidos, la "codificación de longitud de ejecución" de R describe concisamente un vector en términos de sus ejecuciones. Considerar:

dat <- c(1, 2, 2, 2, 3, 1, 4, 4, 1, 1)

Tenemos una longitud de una carrera de 1s; luego una longitud de tres carreras de 2s; luego una carrera de una longitud de 3s; y así. La codificación de longitud de ejecución de R captura todas las longitudes y valores de las ejecuciones de un vector.

Extensiones

Una ejecución también puede referirse a observaciones consecutivas en datos tabulares. Si bien R no tiene una forma natural de codificarlos, se pueden manejar con rleid desde el paquete data.table (actualmente un enlace sin salida) .

Codificación de longitud de ejecución con `rle`

La codificación de longitud de ejecución captura las longitudes de ejecuciones de elementos consecutivos en un vector. Considere un vector de ejemplo:

dat <- c(1, 2, 2, 2, 3, 1, 4, 4, 1, 1)

La función rle extrae cada ejecución y su longitud:

r <- rle(dat)
r
# Run Length Encoding
#   lengths: int [1:6] 1 3 1 1 2 2
#   values : num [1:6] 1 2 3 1 4 1

Los valores para cada ejecución se capturan en r$values :

r$values
# [1] 1 2 3 1 4 1

Esto captura la primera vez que vimos una serie de 1, luego una serie de 2, luego una serie de 3, luego una serie de 1, y así sucesivamente.

Las longitudes de cada ejecución se capturan en r$lengths :

r$lengths
# [1] 1 3 1 1 2 2

Vemos que la ejecución inicial de 1 fue de longitud 1, la ejecución de 2 que siguió fue de longitud 3, y así sucesivamente.

Identificación y agrupación por corridas en base R

Uno podría querer agrupar sus datos por las ejecuciones de una variable y realizar algún tipo de análisis. Considere el siguiente conjunto de datos simple:

(dat <- data.frame(x = c(1, 1, 2, 2, 2, 1), y = 1:6))
#   x y
# 1 1 1
# 2 1 2
# 3 2 3
# 4 2 4
# 5 2 5
# 6 1 6

La variable x tiene tres ejecuciones: una corrida de longitud 2 con valor 1, una corrida de longitud 3 con valor 2 y una corrida de longitud 1 con valor 1. Podríamos calcular el valor medio de la variable y en cada una de las corridas de la variable x (estos valores medios son 1.5, 4 y 6).

En la base R, primero calcularíamos la codificación de longitud de ejecución de la variable x usando rle :

(r <- rle(dat$x))
# Run Length Encoding
#   lengths: int [1:3] 2 3 1
#   values : num [1:3] 1 2 1

El siguiente paso es calcular el número de ejecución de cada fila de nuestro conjunto de datos. Sabemos que el número total de ejecuciones es la length(r$lengths) , y la longitud de cada ejecución es r$lengths , por lo que podemos calcular el número de ejecución de cada una de nuestras carreras con rep :

(run.id <- rep(seq_along(r$lengths), r$lengths))
# [1] 1 1 2 2 2 3

Ahora podemos usar tapply para calcular el valor medio y para cada ejecución agrupando en el id de ejecución:

data.frame(x=r$values, meanY=tapply(dat$y, run.id, mean))
#   x meanY
# 1 1   1.5
# 2 2   4.0
# 3 1   6.0

Identificación y agrupación por ejecuciones en data.table.

El paquete data.table proporciona una forma conveniente de agrupar por ejecuciones en datos. Considere los siguientes datos de ejemplo:

library(data.table)
(DT <- data.table(x = c(1, 1, 2, 2, 2, 1), y = 1:6))
#    x y
# 1: 1 1
# 2: 1 2
# 3: 2 3
# 4: 2 4
# 5: 2 5
# 6: 1 6

La variable x tiene tres ejecuciones: una corrida de longitud 2 con valor 1, una corrida de longitud 3 con valor 2 y una corrida de longitud 1 con valor 1. Podríamos calcular el valor medio de la variable y en cada una de las corridas de la variable x (estos valores medios son 1.5, 4 y 6).

La función data.table rleid proporciona un id que indica el id de ejecución de cada elemento de un vector:

rleid(DT$x)
# [1] 1 1 2 2 2 3

Entonces, se puede agrupar fácilmente en este ID de ejecución y resumir los datos y :

DT[,mean(y),by=.(x, rleid(x))]
#    x rleid  V1
# 1: 1     1 1.5
# 2: 2     2 4.0
# 3: 1     3 6.0

Codificación de longitud de ejecución para comprimir y descomprimir vectores

Los vectores largos con largas ejecuciones del mismo valor pueden comprimirse significativamente almacenándolos en su codificación de longitud de ejecución (el valor de cada ejecución y el número de veces que se repite ese valor). Como ejemplo, considere un vector de longitud 10 millones con un gran número de 1 y solo un pequeño número de 0:

set.seed(144)
dat <- sample(rep(0:1, c(1, 1e5)), 1e7, replace=TRUE)
table(dat)
#       0       1 
#     103 9999897 

El almacenamiento de 10 millones de entradas requerirá un espacio significativo, pero podemos crear un marco de datos con la codificación de longitud de ejecución de este vector:

rle.df <- with(rle(dat), data.frame(values, lengths))
dim(rle.df)
# [1] 207   2
head(rle.df)
#   values lengths
# 1      1   52818
# 2      0       1
# 3      1  219329
# 4      0       1
# 5      1  318306
# 6      0       1

A partir de la codificación de longitud de ejecución, vemos que los primeros 52,818 valores en el vector son 1, seguidos de un solo 0, seguidos de 219,329 1 consecutivos, seguidos de un 0, y así sucesivamente. La codificación de longitud de ejecución solo tiene 207 entradas, lo que nos exige almacenar solo 414 valores en lugar de 10 millones de valores. Como rle.df es un marco de datos, puede almacenarse utilizando funciones estándar como write.csv .

La descompresión de un vector en la codificación de longitud de ejecución se puede lograr de dos maneras. El primer método es llamar simplemente rep , pasando el values elemento de la codificación por longitud de como primer argumento y la lengths los elementos de la codificación por longitud de como segundo argumento:

decompressed <- rep(rle.df$values, rle.df$lengths)

Podemos confirmar que nuestros datos descomprimidos son idénticos a nuestros datos originales:

identical(decompressed, dat)
# [1] TRUE

El segundo método es utilizar la función inverse.rle incorporada de inverse.rle en el objeto rle , por ejemplo:

rle.obj <- rle(dat)                            # create a rle object here
class(rle.obj)
# [1] "rle"

dat.inv <- inverse.rle(rle.obj)               # apply the inverse.rle on the rle object

Podemos confirmar de nuevo que esto produce exactamente el dat original:

identical(dat.inv, dat)
# [1] TRUE


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow