R Language
Codifica run-length
Ricerca…
Osservazioni
Una corsa è una sequenza consecutiva di valori o osservazioni ripetuti. Per i valori ripetuti, la "codifica run-length" di R descrive concisamente un vettore in termini di sue esecuzioni. Tenere conto:
dat <- c(1, 2, 2, 2, 3, 1, 4, 4, 1, 1)
Abbiamo una durata di una corsa di 1 s; quindi una durata di tre secondi di 2 secondi; quindi una durata di una corsa di 3 secondi; e così via. La codifica run-length di R cattura tutte le lunghezze e i valori delle corse di un vettore.
estensioni
Una corsa può anche riferirsi a osservazioni consecutive in un dato tabellare. Mentre R non ha un modo naturale di codificarli, possono essere gestiti con rleid
dal pacchetto data.table (attualmente un link dead-end) .
Codifica run-length con `rle`
La codifica run-length cattura le lunghezze delle esecuzioni di elementi consecutivi in un vettore. Considera un vettore di esempio:
dat <- c(1, 2, 2, 2, 3, 1, 4, 4, 1, 1)
La funzione rle
estrae ogni corsa e la sua lunghezza:
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
I valori per ogni corsa sono catturati in r$values
:
r$values
# [1] 1 2 3 1 4 1
Ciò dimostra che abbiamo visto per la prima volta una serie di 1, una di 2, una di 3, una di 1 e così via.
Le lunghezze di ogni corsa sono catturate in r$lengths
:
r$lengths
# [1] 1 3 1 1 2 2
Vediamo che la serie iniziale di 1 era di lunghezza 1, la serie di secondi che seguì era di lunghezza 3, e così via.
Identificazione e raggruppamento per esecuzioni in base R
Si potrebbe desiderare di raggruppare i propri dati con le analisi di una variabile ed eseguire una sorta di analisi. Si consideri il seguente set di dati semplice:
(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 variabile x
ha tre esecuzioni: una corsa di lunghezza 2 con valore 1, una corsa di lunghezza 3 con valore 2 e una corsa di lunghezza 1 con valore 1. Potremmo voler calcolare il valore medio della variabile y
in ognuna delle corse di variabile x
(questi valori medi sono 1.5, 4 e 6).
Nella base R, dovremmo prima calcolare la codifica run-length della variabile x
usando rle
:
(r <- rle(dat$x))
# Run Length Encoding
# lengths: int [1:3] 2 3 1
# values : num [1:3] 1 2 1
Il prossimo passo è calcolare il numero di esecuzione di ogni riga del nostro set di dati. Sappiamo che il numero totale di esecuzioni è di length(r$lengths)
e la lunghezza di ogni corsa è di r$lengths
, quindi possiamo calcolare il numero di esecuzioni di ciascuna delle nostre esecuzioni con rep
:
(run.id <- rep(seq_along(r$lengths), r$lengths))
# [1] 1 1 2 2 2 3
Ora possiamo usare tapply
per calcolare il valore y
medio per ogni corsa raggruppando sull'id di esecuzione:
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
Identificazione e raggruppamento per esecuzioni in data.table
Il pacchetto data.table offre un modo conveniente per raggruppare mediante le esecuzioni nei dati. Considera i seguenti dati di esempio:
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 variabile x
ha tre esecuzioni: una corsa di lunghezza 2 con valore 1, una corsa di lunghezza 3 con valore 2 e una corsa di lunghezza 1 con valore 1. Potremmo voler calcolare il valore medio della variabile y
in ognuna delle corse di variabile x (questi valori medi sono 1.5, 4 e 6).
La funzione rleid rleid
fornisce un id che indica l'id di esecuzione di ciascun elemento di un vettore:
rleid(DT$x)
# [1] 1 1 2 2 2 3
Si può quindi facilmente raggruppare su questo ID di esecuzione e riepilogare i dati 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
Codifica run-length per comprimere e decomprimere i vettori
I vettori lunghi con long run dello stesso valore possono essere compressi in modo significativo memorizzandoli nella loro codifica run-length (il valore di ogni esecuzione e il numero di volte in cui il valore viene ripetuto). Ad esempio, considera un vettore di lunghezza 10 milioni con un numero enorme di 1 e solo un piccolo numero di 0:
set.seed(144)
dat <- sample(rep(0:1, c(1, 1e5)), 1e7, replace=TRUE)
table(dat)
# 0 1
# 103 9999897
Memorizzare 10 milioni di voci richiederà uno spazio significativo, ma possiamo invece creare un frame di dati con la codifica run-length di questo vettore:
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
Dalla codifica run-length, vediamo che i primi 52.818 valori nel vettore sono 1, seguiti da un singolo 0, seguiti da 219.329 1 consecutivi, seguiti da uno 0 e così via. La codifica run-length ha solo 207 voci, richiedendoci di memorizzare solo 414 valori invece di 10 milioni di valori. Poiché rle.df
è un frame di dati, può essere memorizzato utilizzando funzioni standard come write.csv
.
La decompressione di un vettore nella codifica run-length può essere eseguita in due modi. Il primo metodo consiste nel chiamare semplicemente rep
, passando l'elemento values
della codifica run-length come primo argomento e l'elemento lengths
della codifica run-length come secondo argomento:
decompressed <- rep(rle.df$values, rle.df$lengths)
Possiamo confermare che i nostri dati decompressi sono identici ai nostri dati originali:
identical(decompressed, dat)
# [1] TRUE
Il secondo metodo consiste nell'utilizzare la funzione inverse.rle
integrata di rle
sull'oggetto rle
, ad esempio:
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
Possiamo confermare ancora che questo produce esattamente il dat
originale:
identical(dat.inv, dat)
# [1] TRUE