rle/0000755000176200001440000000000015015614472011041 5ustar liggesusersrle/MD50000644000176200001440000000212315015614472011347 0ustar liggesusers4b0f789012d741fe52a32b2fa8ee5b00 *DESCRIPTION 144e14fb91400a55a42bbaac4ce95bbd *NAMESPACE 0fd26d4253e1a40039995974c7b4d83b *NEWS b42a036dcfbd33105cfdf84e77677cc8 *NEWS.md c06cd3106466c47db3ff0322ed58013b *R/AAA.R 204dfad02d6b015ac3868f9efd264358 *R/extract.R b77db566bafad737771e82c51fb95e7e *R/methods.R 94dbfa38dc40f407dee13deab684e9f0 *R/zzz.R fe2fb57be545acafadd6fe5b0715a194 *build/stage23.rdb 9be87c76d940ef572e9f6a6a9dd93257 *inst/COPYRIGHT c67956a0c8ec4ed54c34c6d789f96192 *man/Extract.rle.Rd eecad48c9bf075f42132b88b5f8c9ee8 *man/Math.rle.Rd 47a5ab0e66f3284248b3d95ac9f0f509 *man/Ops.rle.Rd 3192a7be2c2c84016573059f9fe971a5 *man/Summary.rle.Rd c10b116aa34fe1e7322c023e02c8aaed *man/as.rle.Rd 5dc0fcdba473cf13894aec18b0ce982f *man/compress.Rd 7e44cd5fe8d1b0191bf97db81901bfa7 *man/compress.rle.Rd 6dee1aa29ed1527dc94ef72ea8a41ab1 *man/index_to_run.Rd 682483619221a850cea61ddf01ce8b6e *man/rep.rle.Rd d64d3284064e59e500264a8534eee357 *man/rle-methods.Rd 5c39f748d1097b6dd9e3c62d5cbcb4ca *man/rle-package.Rd 30c36953bcd73874f605aa130a560529 *src/init.c 3bfdce68fd2f5cfa85605dfadd80e20b *src/methods.c rle/R/0000755000176200001440000000000015015604661011241 5ustar liggesusersrle/R/AAA.R0000644000176200001440000000330315015551572011747 0ustar liggesusers# File R/AAA.R in package rle, currently hosted at # https://github.com/statnet/rle . # # This software is distributed under the GNU General Public License Version 3 # or later. A copy of this license may be found at # https://www.gnu.org/licenses/gpl-3.0.en.html . # # Copyright 2017-2025 Pavel N. Krivitsky and others (see inst/COPYRIGHT). ################################################################################ #' @description Common [`base`] and [`stats`] #' methods for [`rle`] objects, aiming to make it possible to treat #' them transparently as vectors. #' #' @section 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. #' #' @section 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 an `rle` object. See [Extract.rle] for more #' details. #' #' * Method [`rep.rle`] currently has limited functionality. "_PACKAGE" rle/R/zzz.R0000644000176200001440000000101015015551572012213 0ustar liggesusers# File R/zzz.R in package rle, currently hosted at # https://github.com/statnet/rle . # # This software is distributed under the GNU General Public License Version 3 # or later. A copy of this license may be found at # https://www.gnu.org/licenses/gpl-3.0.en.html . # # Copyright 2017-2025 Pavel N. Krivitsky and others (see inst/COPYRIGHT). ################################################################################ #' @useDynLib rle .onUnload <- function(libpath){ library.dynam.unload("rle",libpath) } rle/R/extract.R0000644000176200001440000001076015015604437013043 0ustar liggesusers# File R/extract.R in package rle, currently hosted at # https://github.com/statnet/rle . # # This software is distributed under the GNU General Public License Version 3 # or later. A copy of this license may be found at # https://www.gnu.org/licenses/gpl-3.0.en.html . # # Copyright 2017-2025 Pavel N. Krivitsky and others (see inst/COPYRIGHT). ################################################################################ #' @name Extract.rle #' #' @title 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. #' #' @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. #' #' @details At this time, the \pkg{rle} following form of indexing are #' supported: #' #' \tabular{lll}{ #' \strong{operation} \tab \strong{index} \tab \strong{effect} \cr #' `[` \tab `numeric >= 0` \tab as vector \cr #' `[` \tab `numeric < 0` \tab no \cr #' `[` \tab `logical` \tab no \cr #' `[` \tab `character` \tab on rle \cr #' `[<-` \tab `numeric >= 0` \tab no \cr #' `[<-` \tab `numeric < 0` \tab no \cr #' `[<-` \tab `logical` \tab no \cr #' `[<-` \tab `character` \tab on rle \cr #' `[[` \tab `numeric` \tab as vector \cr #' `[[<-` \tab `numeric` \tab no \cr #' `[[` \tab `character` \tab on `rle` \cr #' `[[<-` \tab `character` \tab on `rle` \cr #' `$` \tab `character` \tab on `rle` \cr #' `$<-` \tab `character` \tab on `rle` #' } #' #' Generally, character indexes will access the underlying elements of #' the [`rle`] object, `$lengths` and `$values`. #' #' @param x,i,name,value,... Arguments to indexing operators. See #' [Extract] documentation in the \pkg{base} package. #' @param unclass Logical: whether to process the arguments as if for #' an ordinary list; default other than `FALSE` can be set with #' `options(rle.unclass_index=...)`. #' #' @return 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). #' #' @seealso [index_to_run()] #' @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])) NULL IDXERR <- paste("Indexing of", sQuote("rle"), "objects by logical or negative", "numeric indexes is not implemented at this time.") # TODO: This is built into R 4.4, so delete around mid 2026. `%||%` <- function(x, y) if (is.null(x)) y else x #' @rdname Extract.rle #' @export `[.rle` <- function(x, i, ..., unclass = getOption("rle.unclass_index") %||% FALSE) { if (is.character(i) || unclass) NextMethod() # TODO: This can almost certainly be optimised. else if (is.numeric(i) && all(i >= 0L, na.rm = TRUE)) rle(x$values[index_to_run(x, i)]) else stop(IDXERR) } #' @rdname Extract.rle #' @export `[<-.rle` <- function(x, i, ..., unclass = getOption("rle.unclass_index") %||% FALSE, value) { if (is.character(i) || unclass) NextMethod() else stop(IDXERR) } #' @rdname Extract.rle #' @export `[[.rle` <- function(x, i, ..., unclass = getOption("rle.unclass_index") %||% FALSE) { if (is.character(i) || unclass) NextMethod() else if (is.numeric(i)) x$values[[index_to_run(x, i)]] else stop(IDXERR) } #' @rdname Extract.rle #' @export `[[<-.rle` <- function(x, i, ..., unclass = getOption("rle.unclass_index") %||% FALSE, value) { if (is.character(i) || unclass) NextMethod() else stop(IDXERR) } #' @rdname Extract.rle #' @export `$.rle` <- function(x, name) { NextMethod() } #' @rdname Extract.rle #' @export `$<-.rle` <- function(x, name, value) { NextMethod() } rle/R/methods.R0000644000176200001440000004450315015551572013037 0ustar liggesusers# File R/methods.R in package rle, currently hosted at # https://github.com/statnet/rle . # # This software is distributed under the GNU General Public License Version 3 # or later. A copy of this license may be found at # https://www.gnu.org/licenses/gpl-3.0.en.html . # # Copyright 2017-2025 Pavel N. Krivitsky and others (see inst/COPYRIGHT). ################################################################################ .check_lengths <- function(rle1, rle2){ if(sum(as.numeric(rle1$lengths))!=sum(as.numeric(rle2$lengths))) stop("At this time, binary rle operators require the vectors represented by the encoding to have equal lengths.") } #' Safe multiplication of integer run lengths. #' #' Return a vector of run lengths each no larger than maximum #' representable integer that sum to the product of the arguments. If #' the product is 0, an empty integer vector is returned. #' #' @param e1,e2 arguments to multiply, both `<=.Machine$integer.max`. #' #' @noRd .run_mul <- function(e1, e2){ o <- as.numeric(e1)*as.numeric(e2) if(o > .Machine$integer.max){ # Integer overflow. c(as.integer(rep.int(.Machine$integer.max, o %/% .Machine$integer.max)), as.integer(o %% .Machine$integer.max)) }else if(o==0){ integer(0) }else as.integer(o) } #' @name rle-methods #' #' @title Miscellaneous Common Methods for [`rle`] Objects #' #' @param x,object An [`rle`] object. #' @param na.rm Whether missing values are to be ignored (`TRUE`) or propagated (`FALSE`). #' @param ... For `c`, objects to be concatenated. The first object #' must be of class [`rle`]. #' #' @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))))) #' #' @export c.rle <- function(...){ l <- list(...) l <- lapply(l, as.rle) structure(list( lengths = do.call(c, lapply(l, `[[`, "lengths")), values = do.call(c, lapply(l, `[[`, "values")) ), class = "rle") } #' Unary and Binary Operations for [`rle`] Objects #' #' 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. #' #' @param e1,e2 Arguments to unary (`e1`) and binary (`e1` and `e2`) #' operators. #' #' @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 [`&&`]. #' #' @return 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)))) #' @export Ops.rle <- function(e1, e2){ FUN <- match.fun(.Generic) if(missing(e2)){ # Unary operation structure(list(lengths = e1$lengths, values = FUN(e1$values)), class = "rle") }else if(!nzchar(.Method[1L])){ # e1 is not an rle but e2 is l <- length(e1) if(l == 0L){ structure(list(lengths = integer(0), values = FUN(e1, e2$values)), class = "rle") }else if(l == 1L){ structure(list(lengths = e2$lengths, values = FUN(e1, e2$values)), class = "rle") }else{ stop("Binary operations between a non-scalar and an ", sQuote("rle"), " object are not supported at this time.") } }else if(!nzchar(.Method[2L])){ # e2 is not an rle but e1 is l <- length(e2) if(l == 0L){ structure(list(lengths = integer(0), values = FUN(e1$values, e2)), class = "rle") }else if(l == 1L){ structure(list(lengths = e1$lengths, values = FUN(e1$values, e2)), class = "rle") }else{ stop("Binary operations between an ", sQuote("rle"), " object and a non-scalar are not supported at this time.") } }else{ # Both are rle. .check_lengths(e1, e2) syncinfo <- .Call("sync_RLEs", e1$lengths, e2$lengths) structure(list(lengths = syncinfo$lengths[seq_len(syncinfo$nruns)], values = FUN(e1$values[syncinfo$val1i[seq_len(syncinfo$nruns)]], e2$values[syncinfo$val2i[seq_len(syncinfo$nruns)]])), class = "rle") } } #' Mathematical functions for [`rle`] Objects #' #' Mathematical functions that work independently elementwise on vectors described in [Math] are implemented for [`rle`] objects. See Details for list of exceptions. #' #' @param x An [`rle`] object. #' @param ... 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. #' #' @return 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")) #' @export Math.rle <- function(x, ...){ if(.Generic %in% c("cumsum", "cumprod", "cummax", "cummin")) stop(sQuote(paste0(.Generic,"()")), " method is not yet implemented for ", sQuote("rle"), " objects.") FUN <- match.fun(.Generic) structure(list(lengths = x$lengths, values = FUN(x$values, ...)), class = "rle") } #' Summary methods for [`rle`] objects. #' #' Summarisation functions for vectors described in [Summary] are implemented for [`rle`] objects. #' #' @param ... [`rle`] objects or objects that can be coerced to `rle`. #' @param na.rm Whether the missing values should be ignored (`TRUE`) or propagated (`FALSE`). #' #' @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`. #' #' @return 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)))) #' #' @export Summary.rle <- function(..., na.rm){ FUN <- match.fun(.Generic) inl <- list(...) # If it's just one, strip the length-zero runs and evaluate. if(length(inl) == 1L){ x <- as.rle(inl[[1L]]) keep <- x$lengths!=0L # TODO: Benchmark whether it's better to first check if # any(!keep) or, better yet, write a .Call() function that # returns a flag indicating that as a part of calculating keep. x$values <- x$values[keep] x$lengths <- x$lengths[keep] switch(.Generic, sum = sum(x$values*as.numeric(x$lengths), na.rm = na.rm), prod = prod(x$values^as.numeric(x$lengths), na.rm = na.rm), FUN(x$values, na.rm=na.rm)) # The rest only test existence. }else{ # Otherwise, break up, evaluate individually, and recombine. do.call(FUN, c(lapply(inl, FUN, na.rm=na.rm), na.rm=na.rm)) } } #' A generic function for compressing a data structure. #' #' @param x the object to be compressed. #' #' @param ... additional arguments to methods. #' #' @export compress <- function(x, ...){ UseMethod("compress") } #' Compress the [`rle`] object by merging adjacent runs #' #' @param x an [`rle`] object. #' #' @param ... 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 #' (\Sexpr{.Machine$integer.max}). #' #' @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))) #' @export compress.rle <- function(x, ...){ # First, strip the 0-length runs. x$values <- x$values[x$lengths!=0L] x$lengths <- x$lengths[x$lengths!=0L] # Second, code distinct values as integers if they are not already. remap <- ! storage.mode(x$values) %in% c("integer","logical") if(remap){ vf <- as.integer(as.factor(x$values)) vf[is.na(vf)] <- 0L # NA runs get coded 0. }else vf <- x$values # Third, call the C code to produce the mapping onto the compressed vector. compinfo <- .Call("compress_RLE", x$lengths, vf, remap) # Lastly, rebuild the rle with the combined lengths and remapped values. structure(list(lengths = compinfo$lengths[seq_len(compinfo$nruns)], values = if(remap) x$values[compinfo$vali[seq_len(compinfo$nruns)]] else compinfo$vali[seq_len(compinfo$nruns)]), class = "rle") } #' @rdname rle-methods #' #' @examples #' #' stopifnot(isTRUE(all.equal(mean(inverse.rle(x)),mean(x)))) #' stopifnot(isTRUE(all.equal(mean(inverse.rle(y)),mean(y)))) #' #' @export mean.rle <- function(x, na.rm = FALSE, ...){ if(na.rm) sum(x$values*as.numeric(x$lengths), na.rm = TRUE, ...)/sum(!is.na(x)) else sum(x$values*as.numeric(x$lengths), na.rm = FALSE, ...)/length(x) } #' @rdname rle-methods #' #' @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 #' #' stopifnot(isTRUE(all.equal(length(inverse.rle(x)),length(x)))) #' stopifnot(isTRUE(all.equal(length(inverse.rle(y)),length(y)))) #' #' @export length.rle <- function(x){ if(!is.null(rle_unclass_index <- getOption("rle.unclass_index")) && rle_unclass_index) length(unclass(x)) else sum(as.numeric(x$lengths)) } #' @rdname rle-methods #' #' @examples #' 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))))) #' #' @export is.na.rle <- function(x){ x$values <- is.na(x$values) x } #' A [`rep`] method for [`rle`] objects #' #' @param x an [`rle`] object. #' #' @param ... see documentation for [`rep`]. #' #' @param scale whether to replicate the elements of the #' RLE-compressed vector or the runs. #' #' @param doNotCompress,doNotCompact whether the method should call #' [`compress.rle`] the results before returning. Methods liable to #' produce very long output vectors, like [`rep`], have this set #' `FALSE` by default. `doNotCompact` is an old name for this argument. #' #' @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"))))) #' #' @export rep.rle <- function(x, ..., scale = c("element", "run"), doNotCompact = FALSE, doNotCompress = doNotCompact){ if(!missing(doNotCompact)) .Deprecated(msg=paste("Argument", sQuote("doNotCompact="), "to", sQuote("rep.rle()"), "is deprecated and has been renamed to", sQuote("doNotCompress="), ".")) scale <- match.arg(scale) ddd <- list(...) if(is.null(names(ddd)) && length(ddd)==1) names(ddd) <- "times" if(scale=="element" && length(ddd$times)!=1) stop("RLE on element scale is not supported at this time for vector ",sQuote("times")," argument.") if(length(x$lengths)==length(ddd$times)){ # This handles the specific scale="run" AND times is vector of appropriate length case. tmp <- mapply(function(v, l, times){ newl <- .run_mul(l, times) newv <- rep(v, length(newl)) list(l = newl, v = newv) }, x$values, x$lengths, ddd$times, SIMPLIFY=FALSE) x$values <- as.vector(unlist(sapply(tmp, `[[`, "v"))) x$lengths <- as.integer(unlist(sapply(tmp, `[[`, "l"))) }else{ # This handles the scale="run" OR times is scalar case. x$values <- rep(x$values, ...) x$lengths <- rep(x$lengths, ...) } if(doNotCompress) x else compress(x) } #' Coerce to [`rle`] if not already an [`rle`] object #' #' @param x the object to be coerced. #' #' @export as.rle <- function(x){ UseMethod("as.rle") } #' @rdname as.rle #' @export as.rle.rle <- function(x) x #' @rdname as.rle #' @export as.rle.default <- function(x){ #' @importFrom methods is if(is(x, "rle")) x else rle(x) } #' @rdname rle-methods #' #' @examples #' #' str(x) #' #' @export str.rle <- function(object, ...){ # This is needed because `str` needs the length of the underlying # list rather than that represented by the RLE. op <- options(rle.unclass_index = TRUE) on.exit(options(op)) NextMethod("str") } #' Map an element in a vector represented by an [`rle`] to its run #' #' @param x an [`rle`] object. #' @param i a numeric vector of indices to map; fractional values are #' rounded down. #' @param ... additional arguments to methods. #' #' @note This function is generic for future-proofing. #' #' @return 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. #' #' @export index_to_run <- function(x, i, ...) UseMethod("index_to_run") #' @rdname index_to_run #' #' @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) #' )) #' @export index_to_run.rle <- function(x, i, ...) { i <- floor(i) i <- pmax(i, 0L) # Calculate the run ends, handling integer overflow if needed. # # TODO: We might want to have an option() as to whether to try # with ints first or to go directly to double. ends <- tryCatch( cumsum(c(1L, x$lengths)), warning = function(w) { if (startsWith(w$message, "integer overflow")) cumsum(as.numeric(c(1L, x$lengths))) else stop(sQuote("rle"), " index calculation failed") }) # Calculate to which run each value of i belongs. .bincode(i, c(0L, ends, max(i, ends[length(ends)], na.rm = TRUE) + 1L), right = FALSE) - 1L } rle/NEWS0000644000176200001440000000055215015551572011543 0ustar liggesusersrle 0.10 ======== - Indexing by positive numeric indices using `[` and `[[` operators now works for extraction, though not assignment. - A helper function, `index_to_run()` can be used to map the index of an element represented in an `rle` the run that contains it. rle 0.9 ======= - Initial release, split out of the `statnet.common` package. rle/src/0000755000176200001440000000000015015604661011627 5ustar liggesusersrle/src/methods.c0000644000176200001440000000716215015551572013446 0ustar liggesusers/* File src/methods.c in package rle, currently hosted at * https://github.com/statnet/rle . * * This software is distributed under the GNU General Public License Version 3 * or later. A copy of this license may be found at * https://www.gnu.org/licenses/gpl-3.0.en.html . * * Copyright 2017-2025 Pavel N. Krivitsky and others (see inst/COPYRIGHT). */ #include #include #include SEXP sync_RLEs(SEXP lens1, SEXP lens2){ const char *names[] = {"lengths", "val1i", "val2i", "nruns", ""}; SEXP out = PROTECT(mkNamed(VECSXP, names)); SEXP lengths = PROTECT(allocVector(INTSXP, length(lens1)+length(lens2))); SEXP v1i = PROTECT(allocVector(INTSXP, length(lens1)+length(lens2))); SEXP v2i = PROTECT(allocVector(INTSXP, length(lens1)+length(lens2))); SEXP nruns = PROTECT(allocVector(INTSXP, 1)); // Leftover lengths of the current run in each vector: unsigned int left1 = 0, left2 = 0; // Positions in the RLE length vectors: unsigned int opos = 0, pos1 = 0, pos2 = 0; /* Iteratate through the length vectors. Note that we increment the position as soon as we read from a vector, so it's already in "R" indexing (from 1). */ while(pos1 < length(lens1)){ left1 += INTEGER(lens1)[pos1]; pos1++; while(left1 > left2){ /* Now, we know that left1 > left2. So, we flush from both rle1 and rle2 by the left2's amount, and add on to left2 until left2 is the one "sticking out". */ if(left2 != 0){ INTEGER(lengths)[opos] = left2; INTEGER(v1i)[opos] = pos1; INTEGER(v2i)[opos] = pos2; left1 -= left2; left2 = 0; // I.e., subtract left2 from left2. opos++; } if(pos2 >= length(lens2)) break; left2 += INTEGER(lens2)[pos2]; pos2++; } /* Now, left1 <= left2. (If lens2 has run out, then this should still hold, since the uncompressed lengths of the input vectors must be equal.) So, we flush from both by the left1's amount. */ if(left1 != 0){ INTEGER(lengths)[opos] = left1; INTEGER(v1i)[opos] = pos1; INTEGER(v2i)[opos] = pos2; left2 -= left1; left1 = 0; // I.e., subtract left1 from left1. opos++; } } *INTEGER(nruns) = opos; SET_VECTOR_ELT(out, 0, lengths); SET_VECTOR_ELT(out, 1, v1i); SET_VECTOR_ELT(out, 2, v2i); SET_VECTOR_ELT(out, 3, nruns); UNPROTECT(5); return(out); } SEXP compress_RLE(SEXP lR, SEXP vR, SEXP remapR){ Rboolean remap = asLogical(remapR); unsigned int *l = (unsigned int *) INTEGER(lR), *v = (unsigned int *) INTEGER(vR); const char *names[] = {"lengths", "vali", "nruns", ""}; SEXP outR = PROTECT(mkNamed(VECSXP, names)); SEXP lengthsR = PROTECT(allocVector(INTSXP, length(lR))); SEXP voR = PROTECT(allocVector(TYPEOF(vR), length(lR))); SEXP nrunsR = PROTECT(allocVector(INTSXP, 1)); unsigned int *lengths = (unsigned int *) INTEGER(lengthsR), *vo = (unsigned int *) INTEGER(voR), *nruns = (unsigned int *) INTEGER(nrunsR); lengths[0] = l[0]; vo[0] = remap? 1 : v[0]; unsigned int o = 0; for(unsigned int i = 1; i < length(lR); i++){ unsigned int nextl = l[i]; if(lengths[o] > INT_MAX-nextl || // If cumulative run is too long or (remap? v[vo[o]-1] : vo[o]) != v[i]){ // the value is not the same as the current one... // advance the output vector; o++; lengths[o] = nextl; vo[o] = remap ? i+1 : v[i]; }else{ // otherwise... // stay put and add to the run length. lengths[o] += nextl; } } *nruns = o+1; SET_VECTOR_ELT(outR, 0, lengthsR); SET_VECTOR_ELT(outR, 1, voR); SET_VECTOR_ELT(outR, 2, nrunsR); UNPROTECT(4); return(outR); } rle/src/init.c0000644000176200001440000000160615015551572012743 0ustar liggesusers/* File src/init.c in package rle, currently hosted at * https://github.com/statnet/rle . * * This software is distributed under the GNU General Public License Version 3 * or later. A copy of this license may be found at * https://www.gnu.org/licenses/gpl-3.0.en.html . * * Copyright 2017-2025 Pavel N. Krivitsky and others (see inst/COPYRIGHT). */ #include #include #include // for NULL #include extern SEXP sync_RLEs(SEXP, SEXP); extern SEXP compress_RLE(SEXP, SEXP, SEXP); static const R_CallMethodDef CallEntries[] = { {"sync_RLEs", (DL_FUNC) &sync_RLEs, 2}, {"compress_RLE", (DL_FUNC) &compress_RLE, 3}, {NULL, NULL, 0} }; void R_init_statnet_common(DllInfo *dll) { R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, FALSE); } rle/NAMESPACE0000644000176200001440000000101015015551572012251 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method("$",rle) S3method("$<-",rle) S3method("[",rle) S3method("[<-",rle) S3method("[[",rle) S3method("[[<-",rle) S3method(Math,rle) S3method(Ops,rle) S3method(Summary,rle) S3method(as.rle,default) S3method(as.rle,rle) S3method(c,rle) S3method(compress,rle) S3method(index_to_run,rle) S3method(is.na,rle) S3method(length,rle) S3method(mean,rle) S3method(rep,rle) S3method(str,rle) export(as.rle) export(compress) export(index_to_run) importFrom(methods,is) useDynLib(rle) rle/NEWS.md0000644000176200001440000000051715015551572012143 0ustar liggesusers# rle 0.10 * Indexing by positive numeric indices using `[` and `[[` operators now works for extraction, though not assignment. * A helper function, `index_to_run()` can be used to map the index of an element represented in an `rle` the run that contains it. # rle 0.9 * Initial release, split out of the `statnet.common` package. rle/inst/0000755000176200001440000000000015015551572012017 5ustar liggesusersrle/inst/COPYRIGHT0000644000176200001440000000037415015551572013316 0ustar liggesusersCopyright 2017-2025 * Pavel N. Krivitsky * The following institutions, as a part of their intellectual property policies, may assert copyright over parts of the code in this package: * University of Wollongong (2017-2019) * UNSW Sydney (2019-2025) rle/build/0000755000176200001440000000000015015604661012137 5ustar liggesusersrle/build/stage23.rdb0000644000176200001440000000636115015604661014106 0ustar liggesusers\W@ym6/%֤`&,%pNIXCtnXmdɕdd~{gHWh<2Y_=x7"IRN$){ꓤ~J/iйi6\Cٶ|,klZ5ݥ_"Ss`E{:^\ ;j1F?\"gtv@~DMr~+`S4ݬs M7la=3w°\hDǿȪ`\֛w )PcPle,Wȯ?n2˕jK7ŅG_>Y=Xzm,Vic)?*5nIG]Q"m7  U߈Z;/3*O~Ie``?:4Km5"WLY7J]KsJ A\J?5ؖp$'Q^y.@FsI' ΚWNTׅNp օ&Ћ'2pA:r"z dI0t #sp^.cBjB>#.SOeʆn~:{pZ%2HiS;,[5i lI"#{$-I&3@ׁ_0]5%/> GFa '_yfm]‘-y?h:DtBT 2 5uQJm7v;\!ۺ&݄yאM.2GS" f ]JMFWNfM"uff%#릋vxg@_[Nt#u[o< ߜ| |+~p}VB?0!TDMn5ej;udaӯMyʨȌsOZ~5:Lj =u 1.ˀ c`8gXG.,>Y\zxIo<]gϖZBT^0|wu5DQD ]}ixF:5Ech.j")Z|F i%Hg2)E (UݴŅs s'o|)q`%{^ls4~E^#k6F#6=Ҝafg؏sAwT<9Lb՛Ov9UoƪUNql\4t-BBmbiK tP^{L[۠ogI!NX\Kn|2K'ӹ;ٸb'ؐaQtu2҄eH7.sȲ\DRF \lIxj)OsVBJl\ 5 }#t|cNgk |]?<'IR,Z(U/NPt_}:~X4~g0]Q2n9&nڅRМ,-%QJ&l ն -1(H[p*ԝ&˰ЖRjzt8%N_Qv*;N(ؾx8! #UVǠ-~#.8$k5׀ڧ\qʐb5 Q]=%ЩwlK2ð7;* BehB+5l8xWPn/tV!@+ 9ׄ`B)M6aq[(^f$wz@i~e T({>f/;eXDŽb ȺR_f:bh.(Rt01"w1#1 HPZ! dS$vGڣHAR9HTD`ZrÊFf!"M({ٵ1ܐR4CGz`PjۘBe7ZAxꐢ}ӲNp-68aI-*E=֖>Msek'@S*=?8" ^C=-ꓼւ:-4)jI/jU#6ve }" *tC<9/%NF@g[h+5ScFN ;ttgtMրÂPu{; (R(5L3IQpσ&.*M~ ew`kpv&3tSBʞ6vZڜ㒩W7rZ,//W=Sw~ o`=Z6|6y[~R^.o_G}%}, \code{<=}, \code{>=}, \code{!=}, \code{==}, \code{\%\%}, \code{\%/\%}, \code{&}, \code{|}, \code{!}, and \code{xor}; but excludes non-vector logical functions and operators such as \code{\link{isTRUE}} and \code{\link{&&}}. } \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)))) } rle/man/index_to_run.Rd0000644000176200001440000000200015015551572014571 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods.R \name{index_to_run} \alias{index_to_run} \alias{index_to_run.rle} \title{Map an element in a vector represented by an \code{\link{rle}} to its run} \usage{ index_to_run(x, i, ...) \method{index_to_run}{rle}(x, i, ...) } \arguments{ \item{x}{an \code{\link{rle}} object.} \item{i}{a numeric vector of indices to map; fractional values are rounded down.} \item{...}{additional arguments to methods.} } \value{ An integer vector. Negative values of \code{i} and 0 are always mapped to 0. Indexes above the range represented by \code{x} are mapped to the number of runs + 1. } \description{ Map an element in a vector represented by an \code{\link{rle}} to its run } \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) )) } rle/man/Extract.rle.Rd0000644000176200001440000000633615015551572014307 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/extract.R \name{Extract.rle} \alias{Extract.rle} \alias{[.rle} \alias{[<-.rle} \alias{[[.rle} \alias{[[<-.rle} \alias{$.rle} \alias{$<-.rle} \title{Indexing Methods for \code{rle} Objects} \usage{ \method{[}{rle}(x, i, ..., unclass = getOption("rle.unclass_index") \%||\% FALSE) \method{[}{rle}(x, i, ..., unclass = getOption("rle.unclass_index") \%||\% FALSE) <- value \method{[[}{rle}(x, i, ..., unclass = getOption("rle.unclass_index") \%||\% FALSE) \method{[[}{rle}(x, i, ..., unclass = getOption("rle.unclass_index") \%||\% FALSE) <- value \method{$}{rle}(x, name) \method{$}{rle}(x, name) <- value } \arguments{ \item{x, i, name, value, ...}{Arguments to indexing operators. See \link{Extract} documentation in the \pkg{base} package.} \item{unclass}{Logical: whether to process the arguments as if for an ordinary list; default other than \code{FALSE} can be set with \code{options(rle.unclass_index=...)}.} } \value{ For character indices, the corresponding sublists or elements of the \code{rle} object; for numeric indices, for \code{[[} the element at the specified position and for \code{[} an \code{rle} containing the elements at the specified position(s). } \description{ These methods provide indexing functionality for \code{\link{rle}} objects on the scale of the original scale (the elements of the vector that was compressed) where possible. } \details{ At this time, the \pkg{rle} following form of indexing are supported: \tabular{lll}{ \strong{operation} \tab \strong{index} \tab \strong{effect} \cr \code{[} \tab \code{numeric >= 0} \tab as vector \cr \code{[} \tab \code{numeric < 0} \tab no \cr \code{[} \tab \code{logical} \tab no \cr \code{[} \tab \code{character} \tab on rle \cr \verb{[<-} \tab \code{numeric >= 0} \tab no \cr \verb{[<-} \tab \code{numeric < 0} \tab no \cr \verb{[<-} \tab \code{logical} \tab no \cr \verb{[<-} \tab \code{character} \tab on rle \cr \code{[[} \tab \code{numeric} \tab as vector \cr \verb{[[<-} \tab \code{numeric} \tab no \cr \code{[[} \tab \code{character} \tab on \code{rle} \cr \verb{[[<-} \tab \code{character} \tab on \code{rle} \cr \code{$} \tab \code{character} \tab on \code{rle} \cr \verb{$<-} \tab \code{character} \tab on \code{rle} } Generally, character indexes will access the underlying elements of the \code{\link{rle}} object, \verb{$lengths} and \verb{$values}. } \note{ Some of these methods and inputs produce an error in order to future-proof code that depends on the \code{rle} package by preventing their use. } \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])) } \seealso{ \code{\link[=index_to_run]{index_to_run()}} } rle/man/rle-package.Rd0000644000176200001440000000333615015551572014264 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/AAA.R \docType{package} \name{rle-package} \alias{rle} \alias{rle-package} \title{rle: Common Functions for Run-Length Encoded Vectors} \description{ Common \code{\link{base}} and \code{\link{stats}} methods for \code{\link{rle}} objects, aiming to make it possible to treat them transparently as vectors. } \section{History}{ This package grew out of the needs of the \code{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 \code{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. } \section{What works and what doesn't}{ The long-run aim of this package is to make it possible to treat \code{\link{rle}} objects transparently as unnamed vectors. As of this writing, the biggest unimplemented feature are: \itemize{ \item It is possible to use the indexing (\code{[} and \code{[[}) 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 an \code{rle} object. See \link{Extract.rle} for more details. \item Method \code{\link{rep.rle}} currently has limited functionality. } } \seealso{ Useful links: \itemize{ \item Report bugs at \url{https://github.com/statnet/rle/issues} } } \author{ \strong{Maintainer}: Pavel N. Krivitsky \email{pavel@statnet.org} (\href{https://orcid.org/0000-0002-9101-3362}{ORCID}) } rle/man/compress.Rd0000644000176200001440000000057115015551572013742 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods.R \name{compress} \alias{compress} \title{A generic function for compressing a data structure.} \usage{ compress(x, ...) } \arguments{ \item{x}{the object to be compressed.} \item{...}{additional arguments to methods.} } \description{ A generic function for compressing a data structure. } rle/man/compress.rle.Rd0000644000176200001440000000235615015551572014526 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods.R \name{compress.rle} \alias{compress.rle} \title{Compress the \code{\link{rle}} object by merging adjacent runs} \usage{ \method{compress}{rle}(x, ...) } \arguments{ \item{x}{an \code{\link{rle}} object.} \item{...}{additional objects; if given, all arguments are concatenated.} } \description{ Compress the \code{\link{rle}} object by merging adjacent runs } \note{ Since \code{\link{rle}} stores run lengths as integers, \code{\link{compress.rle}} will not merge runs that add up to lengths greater than what can be represented by a 32-bit signed integer (\Sexpr{.Machine$integer.max}). } \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))) } rle/man/rle-methods.Rd0000644000176200001440000000326215015551572014332 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods.R \name{rle-methods} \alias{rle-methods} \alias{c.rle} \alias{mean.rle} \alias{length.rle} \alias{is.na.rle} \alias{str.rle} \title{Miscellaneous Common Methods for \code{\link{rle}} Objects} \usage{ \method{c}{rle}(...) \method{mean}{rle}(x, na.rm = FALSE, ...) \method{length}{rle}(x) \method{is.na}{rle}(x) \method{str}{rle}(object, ...) } \arguments{ \item{...}{For \code{c}, objects to be concatenated. The first object must be of class \code{\link{rle}}.} \item{x, object}{An \code{\link{rle}} object.} \item{na.rm}{Whether missing values are to be ignored (\code{TRUE}) or propagated (\code{FALSE}).} } \description{ Miscellaneous Common Methods for \code{\link{rle}} Objects } \note{ The \code{\link{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 \code{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) } rle/DESCRIPTION0000644000176200001440000000146115015614472012551 0ustar liggesusersPackage: rle Version: 0.10.0 Date: 2025-05-28 Title: Common Functions for Run-Length Encoded Vectors Authors@R: person("Pavel N.", "Krivitsky", role=c("aut","cre"), email="pavel@statnet.org", comment=c(ORCID="0000-0002-9101-3362")) 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 [aut, cre] (ORCID: ) Maintainer: Pavel N. Krivitsky Repository: CRAN Date/Publication: 2025-05-28 14:10:02 UTC