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. |
Authors: | Pavel N. Krivitsky [aut, cre] |
Maintainer: | Pavel N. Krivitsky <[email protected]> |
License: | GPL-3 |
Version: | 0.9.2-234 |
Built: | 2024-11-06 11:13:34 UTC |
Source: | https://github.com/statnet/rle |
rle
PackageCommon base
and stats
methods for rle
objects, aiming to make it possible to treat
them transparently as vectors.
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.
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:
The indexing ([
and [[
) operators. It is not possible to
extract or replace individual elements of the vector represented
by an rle
object, though it is possible to access its
underlying representation (i.e., $lenths
and $values
) by
name using any of the above operators or the $
operator.
Method rep.rle
currently has limited functionality.
rle
if not already an rle
objectCoerce to rle
if not already an rle
object
as.rle(x) ## S3 method for class 'rle' as.rle(x) ## Default S3 method: as.rle(x)
as.rle(x) ## S3 method for class 'rle' as.rle(x) ## Default S3 method: as.rle(x)
x |
the object to be coerced. |
A generic function for compressing a data structure.
compress(x, ...)
compress(x, ...)
x |
the object to be compressed. |
... |
additional arguments to methods. |
rle
object by merging adjacent runsCompress the rle
object by merging adjacent runs
## S3 method for class 'rle' compress(x, ...)
## S3 method for class 'rle' compress(x, ...)
x |
an |
... |
additional objects; if given, all arguments are concatenated. |
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).
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)))
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)))
rle
ObjectsThese methods are defined and produce an error (except
for character
input) to future-proof code that depends on the
rle
package by preventing their use.
## S3 method for class 'rle' x[i, ...] ## S3 replacement method for class 'rle' x[i, ...] <- value ## S3 method for class 'rle' x[[i, ...]] ## S3 replacement method for class 'rle' x[[i, ...]] <- value ## S3 method for class 'rle' x$name ## S3 replacement method for class 'rle' x$name <- value
## S3 method for class 'rle' x[i, ...] ## S3 replacement method for class 'rle' x[i, ...] <- value ## S3 method for class 'rle' x[[i, ...]] ## S3 replacement method for class 'rle' x[[i, ...]] <- value ## S3 method for class 'rle' x$name ## S3 replacement method for class 'rle' x$name <- value
x , i , name , value , ...
|
Arguments to indexing operators. See
Extract documentation in the |
At this time, the rle
package does not support indexing
operations by logical
or numeric
indices, but it is
likely to do so in the future. Therefore, we reserve the syntax
now to prevent users of this package from relying on the default
behaviour of the indexing operators.
At this time, all functions raise an error except for
character
indices. This behaviour can be overridden by
setting options(rle.unclass_index=TRUE)
, which effectively
unclass
es the objects before indexing.
# 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 ## Not run: # Numerical indexing doesn't, unless `options(rle.unclass_index=TRUE)` is set. x[1] x[[1]] ## End(Not run)
# 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 ## Not run: # Numerical indexing doesn't, unless `options(rle.unclass_index=TRUE)` is set. x[1] x[[1]] ## End(Not run)
rle
ObjectsMathematical functions that work independently elementwise on vectors described in Math are implemented for rle
objects. See Details for list of exceptions.
## S3 method for class 'rle' Math(x, ...)
## S3 method for class 'rle' Math(x, ...)
x |
An |
... |
Additional arguments. |
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.
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
.
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"))
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"))
rle
ObjectsUnary and binary Arithmetic and Logic operators (with
exceptions given below) are implemented between two rle
objects
and between an rle
object and a scalar.
## S3 method for class 'rle' Ops(e1, e2)
## S3 method for class 'rle' Ops(e1, e2)
e1 , e2
|
Arguments to unary ( |
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 &&
.
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
.
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))))
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))))
rep
method for rle
objects## S3 method for class 'rle' rep( x, ..., scale = c("element", "run"), doNotCompact = FALSE, doNotCompress = doNotCompact )
## S3 method for class 'rle' rep( x, ..., scale = c("element", "run"), doNotCompact = FALSE, doNotCompress = doNotCompact )
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
|
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).
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")))))
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")))))
rle
Deprecated functions from rle
compact.rle(...)
compact.rle(...)
... |
arguments to deprecated functions. |
rle
ObjectsMiscellaneous Common Methods for rle
Objects
## 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, ...)
## 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, ...)
... |
For |
x , object
|
An |
na.rm |
Whether missing values are to be ignored ( |
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.
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)
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)
rle
objects.Summarisation functions for vectors described in Summary are implemented for rle
objects.
## S3 method for class 'rle' Summary(..., na.rm)
## S3 method for class 'rle' Summary(..., na.rm)
... |
|
na.rm |
Whether the missing values should be ignored ( |
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
.
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.
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))))
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))))