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


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow