运行长度编码以压缩和解压缩向量
通过将它们存储在运行长度编码中(每次运行的值和重复值的次数),可以显着压缩具有相同值的长运行的长向量。举个例子,考虑一个长度为 1000 万的向量,其中包含大量的 1 和 0,只有少量的 0:
set.seed(144)
dat <- sample(rep(0:1, c(1, 1e5)), 1e7, replace=TRUE)
table(dat)
# 0 1
# 103 9999897
存储 1000 万个条目将需要大量空间,但我们可以使用此向量的行程编码来创建数据框:
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
从行程编码中,我们看到向量中的前 52,818 个值是 1,接着是单个 0,接着是 219,329 个连续的 1,然后是 0,依此类推。游程编码只有 207 个条目,要求我们只存储 414 个值而不是 1000 万个值。由于 rle.df
是一个数据框,因此可以使用 write.csv
等标准函数进行存储。
在游程编码中解压缩矢量可以通过两种方式完成。第一种方法是简单地调用 rep
,将游程编码的 values
元素作为第一个参数传递,将游程编码的 lengths
元素作为第二个参数传递:
decompressed <- rep(rle.df$values, rle.df$lengths)
我们可以确认我们的解压缩数据与原始数据相同:
identical(decompressed, dat)
# [1] TRUE
第二种方法是在 rle
对象上使用 R 的内置 inverse.rle
函数,例如:
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
我们可以再次确认这产生了原始的 dat
:
identical(dat.inv, dat)
# [1] TRUE