运行长度编码以压缩和解压缩向量

通过将它们存储在运行长度编码中(每次运行的值和重复值的次数),可以显着压缩具有相同值的长运行的长向量。举个例子,考虑一个长度为 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