| Version: | 0.10.0 |
| Date: | 2025-05-28 |
| Title: | Common Functions for Run-Length Encoded Vectors |
| Description: | Common 'base' and 'stats' methods for 'rle' objects, aiming to make it possible to treat them transparently as vectors. |
| Depends: | R (≥ 3.5) |
| Imports: | methods |
| Copyright: | file inst/COPYRIGHT |
| BugReports: | https://github.com/statnet/rle/issues |
| License: | GPL-3 |
| RoxygenNote: | 7.3.2.9000 |
| Encoding: | UTF-8 |
| Suggests: | covr |
| NeedsCompilation: | yes |
| Packaged: | 2025-05-28 13:03:45 UTC; pavel |
| Author: | Pavel N. Krivitsky
|
| Maintainer: | Pavel N. Krivitsky <pavel@statnet.org> |
| Repository: | CRAN |
| Date/Publication: | 2025-05-28 14:10:02 UTC |
rle: Common Functions for Run-Length Encoded Vectors
Description
Common base and stats
methods for rle objects, aiming to make it possible to treat
them transparently as vectors.
History
This package grew out of the needs of the ergm package for a
run-length encoded representation of extremely long vectors with a
small number of contiguous runs, and these functions were originally
implemented in the statnet.common package.
It has been split out into its own package to enable others to use this functionality without installing any unnecessary dependencies and to facilitate contributions under a simplified license.
What works and what doesn't
The long-run aim of this package is to make it possible to treat
rle objects transparently as unnamed vectors. As of this
writing, the biggest unimplemented feature are:
It is possible to use the indexing (
[and[[) operators to extract by positive numeric indices but not by logical or negative numeric indices, and the implementation is far from optimal. It is not possible to replace individual elements of the vector represented by anrleobject. See Extract.rle for more details.Method
rep.rlecurrently has limited functionality.
Author(s)
Maintainer: Pavel N. Krivitsky pavel@statnet.org (ORCID)
See Also
Useful links:
Report bugs at https://github.com/statnet/rle/issues
Indexing Methods for rle Objects
Description
These methods provide indexing functionality for
rle objects on the scale of the original scale (the elements
of the vector that was compressed) where possible.
Usage
## S3 method for class 'rle'
x[i, ..., unclass = getOption("rle.unclass_index") %||% FALSE]
## S3 replacement method for class 'rle'
x[i, ..., unclass = getOption("rle.unclass_index") %||% FALSE] <- value
## S3 method for class 'rle'
x[[i, ..., unclass = getOption("rle.unclass_index") %||% FALSE]]
## S3 replacement method for class 'rle'
x[[i, ..., unclass = getOption("rle.unclass_index") %||% FALSE]] <- value
## S3 method for class 'rle'
x$name
## S3 replacement method for class 'rle'
x$name <- value
Arguments
x, i, name, value, ... |
Arguments to indexing operators. See Extract documentation in the base package. |
unclass |
Logical: whether to process the arguments as if for
an ordinary list; default other than |
Details
At this time, the rle following form of indexing are supported:
| operation | index | effect |
[ | numeric >= 0 | as vector |
[ | numeric < 0 | no |
[ | logical | no |
[ | character | on rle |
[<- | numeric >= 0 | no |
[<- | numeric < 0 | no |
[<- | logical | no |
[<- | character | on rle |
[[ | numeric | as vector |
[[<- | numeric | no |
[[ | character | on rle |
[[<- | character | on rle |
$ | character | on rle |
$<- | character | on rle
|
Generally, character indexes will access the underlying elements of
the rle object, $lengths and $values.
Value
For character indices, the corresponding sublists or
elements of the rle object; for numeric indices, for [[ the
element at the specified position and for [ an rle containing the
elements at the specified position(s).
Note
Some of these methods and inputs produce an error in
order to future-proof code that depends on the rle package by
preventing their use.
See Also
Examples
# Indexing by character or by $ works, including sub-indexing.
x <- rle(1:5)
x[["values"]] <- 2:6
x
x$values[2:3] <- 7:8
x
# From example(rle):
z <- c(TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE)
rle(z)
rle(z)[3:5] # Extract a sub-rle
rle(z)[[4]] # Extract an element
stopifnot(identical(inverse.rle(rle(z)[3:5]), z[3:5]))
# Fractional:
stopifnot(identical(inverse.rle(rle(z)[3.5]), z[3.5]))
# Zero:
stopifnot(identical(inverse.rle(rle(z)[0]), z[0]))
# Out of range:
stopifnot(identical(inverse.rle(rle(z)[20]), z[20]))
# A mix:
strange <- c(20, 3:5, 0, NA, 1:2)
stopifnot(identical(inverse.rle(rle(z)[strange]), z[strange]))
Mathematical functions for rle Objects
Description
Mathematical functions that work independently elementwise on vectors described in Math are implemented for rle objects. See Details for list of exceptions.
Usage
## S3 method for class 'rle'
Math(x, ...)
Arguments
x |
An |
... |
Additional arguments. |
Details
Supported functions include all elements of the S3 Math
group excluding the "cumulative" ones, which are not supported at
this time and will raise an error. As of this writing, functions
supported include (from R help) abs, sign, sqrt, floor,
ceiling, trunc, round, signif, exp, log, expm1,
log1p, cos, sin, tan, cospi, sinpi, tanpi, acos,
asin, atan, cosh, sinh, tanh, acosh, asinh,
atanh, lgamma, gamma, digamma, and trigamma.
Functions cumsum, cumprod, cummax, and cummin are not
supported at this time and will raise an error.
Value
In every supported case, the call should result in an
rle that would have resulted had the call been applied to the
original (uncompressed) vector, then compressed using
rle. (At no point in the calculation is the uncompressed
vector actually constructed, of course.)
By default, the functions do not merge adjacent
runs with the same value. This must be done explicitly with
compress.rle.
Examples
x <- rle(sample(runif(2), 10, c(.7,.3), replace=TRUE))
stopifnot(isTRUE(all.equal(sin(inverse.rle(x)),inverse.rle(sin(x)))))
stopifnot(inherits(try(cumprod(x)), "try-error"))
Unary and Binary Operations for rle Objects
Description
Unary and binary Arithmetic and Logic operators (with
exceptions given below) are implemented between two rle objects
and between an rle object and a scalar.
Usage
## S3 method for class 'rle'
Ops(e1, e2)
Arguments
e1, e2 |
Arguments to unary ( |
Details
Supported operations include all elements of the Ops
group, as well as xor. Within the Arithmetic and Logic
operators, this includes (taken from the R help): +, -, *,
/, ^, < , >, <=, >=, !=, ==, %%, %/%, &,
|, !, and xor; but excludes non-vector logical functions
and operators such as isTRUE and &&.
Value
In every supported case, the operation should result in an
rle that would have resulted had the operation been applied
to the original (uncompressed) vectors, then compressed using
rle, with the proviso that if the resulting function creates
adjacent runs of the same value, they are not merged. This must
be done explicitly with compress.rle. (At no point in the
calculation are the uncompressed vectors actually constructed, of
course.)
An operation between an rle and a zero-length object produces
an empty rle.
Examples
x <- rle(as.logical(rbinom(10,1,.7)))
y <- rle(as.logical(rbinom(10,1,.3)))
stopifnot(isTRUE(all.equal((!inverse.rle(x)),inverse.rle(!x))))
stopifnot(isTRUE(all.equal((inverse.rle(x)|inverse.rle(y)),inverse.rle(x|y))))
stopifnot(isTRUE(all.equal((inverse.rle(x)&inverse.rle(y)),inverse.rle(x&y))))
x <- rle(sample(c(-1,+1), 10, c(.7,.3), replace=TRUE))
y <- rle(sample(c(-1,+1), 10, c(.3,.7), replace=TRUE))
stopifnot(isTRUE(all.equal((inverse.rle(x)*inverse.rle(y)),inverse.rle(x*y))))
stopifnot(isTRUE(all.equal((2*inverse.rle(y)),inverse.rle(2*y))))
stopifnot(isTRUE(all.equal((inverse.rle(x)*2),inverse.rle(x*2))))
stopifnot(isTRUE(all.equal((inverse.rle(x)/inverse.rle(y)),inverse.rle(x/y))))
stopifnot(isTRUE(all.equal((2/inverse.rle(y)),inverse.rle(2/y))))
stopifnot(isTRUE(all.equal((inverse.rle(x)/2),inverse.rle(x/2))))
stopifnot(isTRUE(all.equal((-inverse.rle(y)),inverse.rle(-y))))
stopifnot(isTRUE(all.equal((inverse.rle(x)-inverse.rle(y)),inverse.rle(x-y))))
stopifnot(isTRUE(all.equal((inverse.rle(x)%/%inverse.rle(y)),inverse.rle(x%/%y))))
stopifnot(isTRUE(all.equal(inverse.rle(x)==inverse.rle(y),inverse.rle(x==y))))
stopifnot(isTRUE(all.equal((inverse.rle(x)>inverse.rle(y)),inverse.rle(x>y))))
Summary methods for rle objects.
Description
Summarisation functions for vectors described in Summary are implemented for rle objects.
Usage
## S3 method for class 'rle'
Summary(..., na.rm)
Arguments
... |
|
na.rm |
Whether the missing values should be ignored ( |
Details
Supported functions include all elements of the S3
Summary group. As of this writing, functions supported include
(from R help) all, any, max, min, prod, range, and
sum.
Value
In every supported case, the call should produce the same
result as what would have resulted had the call been applied to
the original (uncompressed) vector. (At no point in the
calculation is the uncompressed vector actually constructed, of
course.) The exception is that if values are of class
integer, the result will nonetheless always be upcast to
numeric to avert overflows. This behaviour may change in the
future.
Examples
x <- rle(as.logical(rbinom(20,1,.7)))
y <- rle(as.logical(rbinom(20,1,.3)))
stopifnot(isTRUE(all.equal(any(x, y),any(inverse.rle(x), inverse.rle(y)))))
stopifnot(isTRUE(all.equal(any(y),any(inverse.rle(y)))))
stopifnot(isTRUE(all.equal(sum(inverse.rle(x),inverse.rle(y)),sum(x,y))))
stopifnot(isTRUE(all.equal(sum(inverse.rle(y)),sum(y))))
y$values[2:3] <- NA
stopifnot(isTRUE(all.equal(sum(inverse.rle(y), na.rm=TRUE),sum(y, na.rm=TRUE))))
stopifnot(isTRUE(all.equal(sum(inverse.rle(y), na.rm=FALSE),sum(y, na.rm=FALSE))))
Coerce to rle if not already an rle object
Description
Coerce to rle if not already an rle object
Usage
as.rle(x)
## S3 method for class 'rle'
as.rle(x)
## Default S3 method:
as.rle(x)
Arguments
x |
the object to be coerced. |
A generic function for compressing a data structure.
Description
A generic function for compressing a data structure.
Usage
compress(x, ...)
Arguments
x |
the object to be compressed. |
... |
additional arguments to methods. |
Compress the rle object by merging adjacent runs
Description
Compress the rle object by merging adjacent runs
Usage
## S3 method for class 'rle'
compress(x, ...)
Arguments
x |
an |
... |
additional objects; if given, all arguments are concatenated. |
Note
Since rle stores run lengths as integers, compress.rle
will not merge runs that add up to lengths greater than what can
be represented by a 32-bit signed integer
(2147483647).
Examples
x <- rle(as.logical(rbinom(10,1,.7)))
y <- rle(as.logical(rbinom(10,1,.3)))
stopifnot(identical(rle(inverse.rle(x)&inverse.rle(y)),compress(x&y)))
big <- structure(list(lengths=as.integer(rep(.Machine$integer.max/4,6)),
values=rep(TRUE,6)), class="rle")
stopifnot(all(aggregate(as.numeric(lengths)~values,
data=as.data.frame(unclass(big)),FUN=sum)
==
aggregate(as.numeric(lengths)~values,
data=as.data.frame(unclass(compress(big))),
FUN=sum)))
Map an element in a vector represented by an rle to its run
Description
Map an element in a vector represented by an rle to its run
Usage
index_to_run(x, i, ...)
## S3 method for class 'rle'
index_to_run(x, i, ...)
Arguments
x |
an |
i |
a numeric vector of indices to map; fractional values are rounded down. |
... |
additional arguments to methods. |
Value
An integer vector. Negative values of i and 0 are always
mapped to 0. Indexes above the range represented by x are
mapped to the number of runs + 1.
Note
This function is generic for future-proofing.
Examples
# From example(rle):
z <- c(TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE)
rle(z)
stopifnot(identical(
index_to_run(rle(z), (-1):10),
c(0L, 0L, 1L, 1L, 2L, 2L, 3L, 4L, 5L, 5L, 5L, 6L)
))
A rep method for rle objects
Description
Usage
## S3 method for class 'rle'
rep(
x,
...,
scale = c("element", "run"),
doNotCompact = FALSE,
doNotCompress = doNotCompact
)
Arguments
x |
an |
... |
see documentation for |
scale |
whether to replicate the elements of the RLE-compressed vector or the runs. |
doNotCompress, doNotCompact |
whether the method should call
|
Note
The rep method for rle objects is very limited at
this time. Even though the default setting is to replicate
elements of the vector, only the run-replicating functionality is
implemented at this time except for the simplest case (scalar
times argument).
Examples
x <- rle(sample(c(-1,+1), 10, c(.7,.3), replace=TRUE))
y <- rpois(length(x$lengths), 2)
stopifnot(isTRUE(all.equal(rep(inverse.rle(x), rep(y, x$lengths)),
inverse.rle(rep(x, y, scale="run")))))
stopifnot(isTRUE(all.equal(rep(inverse.rle(x), max(y)),
inverse.rle(rep(x, max(y), scale="element")))))
Miscellaneous Common Methods for rle Objects
Description
Miscellaneous Common Methods for rle Objects
Usage
## S3 method for class 'rle'
c(...)
## S3 method for class 'rle'
mean(x, na.rm = FALSE, ...)
## S3 method for class 'rle'
length(x)
## S3 method for class 'rle'
is.na(x)
## S3 method for class 'rle'
str(object, ...)
Arguments
... |
For |
x, object |
An |
na.rm |
Whether missing values are to be ignored ( |
Note
The length method returns the length of the vector
represented by the object, obtained by summing the lengths of
individual runs. This can be overridden by setting
options(rle.unclass_index = FALSE), which causes it to
return the length of the underlying representation (usually 2) instead.
Examples
x <- rle(as.logical(rbinom(10,1,.7)))
y <- rle(as.logical(rbinom(10,1,.3)))
stopifnot(isTRUE(all.equal(c(inverse.rle(x),inverse.rle(y)),inverse.rle(c(x,y)))))
stopifnot(isTRUE(all.equal(mean(inverse.rle(x)),mean(x))))
stopifnot(isTRUE(all.equal(mean(inverse.rle(y)),mean(y))))
stopifnot(isTRUE(all.equal(length(inverse.rle(x)),length(x))))
stopifnot(isTRUE(all.equal(length(inverse.rle(y)),length(y))))
x$values[1] <- NA
y$values[1] <- NA
stopifnot(isTRUE(all.equal(is.na(inverse.rle(x)),inverse.rle(is.na(x)))))
stopifnot(isTRUE(all.equal(is.na(inverse.rle(y)),inverse.rle(is.na(y)))))
str(x)