R Language
Run-length codering
Zoeken…
Opmerkingen
Een run is een opeenvolgende reeks van herhaalde waarden of waarnemingen. Voor herhaalde waarden beschrijft de "run-length codering" van R een bondige beschrijving van een vector in termen van zijn runs. Overwegen:
dat <- c(1, 2, 2, 2, 3, 1, 4, 4, 1, 1)
We hebben een lengte van één reeks van 1s; dan een lengte-drie run van 2s; dan een lengte van een reeks van 3s; enzovoorts. R's run-length codering vangt alle lengtes en waarden van de runs van een vector.
uitbreidingen
Een run kan ook verwijzen naar opeenvolgende waarnemingen in tabelgegevens. Hoewel R geen natuurlijke manier heeft om deze te coderen, kunnen ze worden afgehandeld met rleid
uit het data.table-pakket (momenteel een doodlopende link) .
Run-length codering met `rle`
Run-length codering legt de lengtes van runs van opeenvolgende elementen in een vector vast. Overweeg een voorbeeldvector:
dat <- c(1, 2, 2, 2, 3, 1, 4, 4, 1, 1)
De functie rle
haalt elke run en de lengte ervan op:
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
De waarden voor elke run worden vastgelegd in r$values
:
r$values
# [1] 1 2 3 1 4 1
Dit geeft aan dat we eerst een reeks van 1'en zagen, vervolgens een reeks van 2'en, dan een reeks van 3'en, dan een reeks van 1'en, enzovoort.
De lengtes van elke run worden vastgelegd in r$lengths
:
r$lengths
# [1] 1 3 1 1 2 2
We zien dat de eerste reeks van 1's van lengte 1 was, de reeks van 2's die volgde lengte 3 had, enzovoort.
Identificeren en groeperen op runs in base R
Misschien wilt u hun gegevens groeperen op basis van de runs van een variabele en een soort analyse uitvoeren. Overweeg de volgende eenvoudige gegevensset:
(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
De variabele x
heeft drie runs: een run van lengte 2 met waarde 1, een run van lengte 3 met waarde 2 en een run van lengte 1 met waarde 1. We willen misschien de gemiddelde waarde van variabele y
berekenen in elk van de reeksen van variabele x
(deze gemiddelde waarden zijn 1,5, 4 en 6).
In base R zouden we eerst de run-length codering van de x
variabele rle
met behulp van rle
:
(r <- rle(dat$x))
# Run Length Encoding
# lengths: int [1:3] 2 3 1
# values : num [1:3] 1 2 1
De volgende stap is om het runnummer van elke rij van onze dataset te berekenen. We weten dat het totale aantal runs length(r$lengths)
, en de lengte van elke run is r$lengths
, dus we kunnen het runnummer van elk van onze runs berekenen met rep
:
(run.id <- rep(seq_along(r$lengths), r$lengths))
# [1] 1 1 2 2 2 3
Nu kunnen we tapply
gebruiken om de gemiddelde y
waarde voor elke run te berekenen door op run-id te groeperen:
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
Identificeren en groeperen op runs in data.table
Het data.table-pakket biedt een handige manier om gegevens in runs te groeperen. Overweeg de volgende voorbeeldgegevens:
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
De variabele x
heeft drie runs: een run van lengte 2 met waarde 1, een run van lengte 3 met waarde 2 en een run van lengte 1 met waarde 1. We willen misschien de gemiddelde waarde van variabele y
berekenen in elk van de reeksen van variabele x (deze gemiddelde waarden zijn 1,5, 4 en 6).
De functie data.table rleid
biedt een id die de run-id van elk element van een vector aangeeft:
rleid(DT$x)
# [1] 1 1 2 2 2 3
Men kan dan eenvoudig deze run ID groeperen en de y
gegevens samenvatten:
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
Run-length codering om vectoren te comprimeren en te decomprimeren
Lange vectoren met lange runs van dezelfde waarde kunnen aanzienlijk worden gecomprimeerd door ze op te slaan in hun run-length codering (de waarde van elke run en het aantal keren dat die waarde wordt herhaald). Beschouw bijvoorbeeld een vector met een lengte van 10 miljoen met een groot aantal enen en slechts een klein aantal enen:
set.seed(144)
dat <- sample(rep(0:1, c(1, 1e5)), 1e7, replace=TRUE)
table(dat)
# 0 1
# 103 9999897
Het opslaan van 10 miljoen items vereist veel ruimte, maar we kunnen in plaats daarvan een gegevensframe maken met de run-length codering van deze 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
Uit de run-length codering zien we dat de eerste 52.818 waarden in de vector 1's zijn, gevolgd door een enkele 0, gevolgd door 219.329 opeenvolgende 1's, gevolgd door een 0, enzovoort. De run-length codering heeft slechts 207 ingangen, waardoor we slechts 414 waarden moeten opslaan in plaats van 10 miljoen waarden. Aangezien rle.df
een gegevensframe is, kan het worden opgeslagen met standaardfuncties zoals write.csv
.
Een vector decomprimeren in run-length codering kan op twee manieren worden bereikt. De eerste methode is om gewoon bellen rep
, passeren de values
element van de run-lengtecodering als eerste argument en lengths
element van de run-lengtecodering als tweede argument:
decompressed <- rep(rle.df$values, rle.df$lengths)
We kunnen bevestigen dat onze gedecomprimeerde gegevens identiek zijn aan onze oorspronkelijke gegevens:
identical(decompressed, dat)
# [1] TRUE
De tweede methode is om de ingebouwde functie inverse.rle
R op het rle
object te gebruiken, bijvoorbeeld:
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
We kunnen opnieuw bevestigen dat dit produceert precies de originele dat
:
identical(dat.inv, dat)
# [1] TRUE