Skip to contents

A set of functions for direct manipulation of the nonzero elements of an array-like object.

Usage

is_nonzero(x)

nzcount(x)
nzwhich(x, arr.ind=FALSE)
nzvals(x)
nzvals(x) <- value

sparsity(x)

Arguments

x

Typically (but not necessarily) an array-like object that is sparse, like a SparseArray derivative, or a dg[C|R]Matrix or lg[C|R]Matrix object from the Matrix package.

However, x can also be an ordinary matrix or array, or any matrix-like or array-like object.

arr.ind

If arr.ind=FALSE (the default), the indices of the nonzero array elements are returned in a numeric vector (a.k.a. L-index). Otherwise, they're returned in an ordinary matrix (a.k.a. M-index).

See ?Lindex in the S4Arrays package for more information about L-index and M-index, and how to convert from one to the other.

Note that using arr.ind=TRUE won't work if nzcount(x) is >= .Machine$integer.max (= 2^31), because, in that case, the returned M-index would need to be a matrix with more rows than what is supported by base R.

value

A vector, typically of length nzcount(x) (or 1) and type type(x).

Details

nzcount(x) and nzwhich(x) are equivalent to, but typically more efficient than, sum(is_nonzero(x)) and which(is_nonzero(x)), respectively.

nzvals(x) is equivalent to, but typically more efficient than, x[nzwhich(x)] (or x[is_nonzero(x)]).

nzvals(x) <- value replaces the values of the nonzero array elements in x with the supplied values. It's equivalent to, but typically more efficient than, x[nzwhich(x)] <- value.

Note that nzvals(x) <- nzvals(x) is guaranteed to be a no-op.

Value

is_nonzero(): An array-like object of type() "logical" and same dimensions as the input object.

nzcount(): The number of nonzero array elements in x.

nzwhich(): The indices of the nonzero array elements in x, either as an L-index (if arr.ind is FALSE) or as an M-index (if arr.ind is TRUE). Note that the indices are returned sorted in strictly ascending order.

nzvals(): A vector of the same type() as x and containing the values of the nonzero array elements in x. Note that the returned vector is guaranteed to be parallel to nzwhich(x).

sparsity(x): The ratio between the number of zero-valued elements in array-like object x and its total number of elements (length(x) or prod(dim(x))). More precisely, sparsity(x) is 1 - nzcount(x)/length(x).

See also

Examples

a <- array(rpois(120, lambda=0.3), dim=c(5, 12, 2))

is_nonzero(a)
#> , , 1
#> 
#>       [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]  [,9] [,10] [,11] [,12]
#> [1,] FALSE FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE
#> [2,]  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE
#> [3,] FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE
#> [4,] FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE  TRUE
#> [5,] FALSE FALSE  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE  TRUE
#> 
#> , , 2
#> 
#>       [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]  [,9] [,10] [,11] [,12]
#> [1,] FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE
#> [2,]  TRUE FALSE  TRUE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE
#> [3,] FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE
#> [4,] FALSE  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
#> [5,]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE
#> 

## Get the number of nonzero array elements in 'a':
nzcount(a)
#> [1] 28

## nzwhich() returns the indices of the nonzero array elements in 'a'.
## Either as a "L-index" i.e. an integer (or numeric) vector of
## length 'nzcount(a)' containing "linear indices":
nzidx <- nzwhich(a)
length(nzidx)
#> [1] 28
head(nzidx)
#> [1]  2 15 21 23 27 28

## Or as an "M-index" i.e. an integer matrix with 'nzcount(a)' rows
## and one column per dimension where the rows represent "array indices"
## (a.k.a. "array coordinates"):
Mnzidx <- nzwhich(a, arr.ind=TRUE)
dim(Mnzidx)
#> [1] 28  3

## Each row in the matrix is an n-tuple representing the "array
## coordinates" of a nonzero element in 'a':
head(Mnzidx)
#>      [,1] [,2] [,3]
#> [1,]    2    1    1
#> [2,]    5    3    1
#> [3,]    1    5    1
#> [4,]    3    5    1
#> [5,]    2    6    1
#> [6,]    3    6    1
tail(Mnzidx)
#>       [,1] [,2] [,3]
#> [23,]    2    8    2
#> [24,]    5    8    2
#> [25,]    3    9    2
#> [26,]    4   10    2
#> [27,]    1   11    2
#> [28,]    3   12    2

## Extract the values of the nonzero array elements in 'a' and return
## them in a vector "parallel" to 'nzwhich(a)':
a_nzvals <- nzvals(a)  # equivalent to 'a[nzwhich(a)]'
length(a_nzvals)
#> [1] 28
head(a_nzvals)
#> [1] 1 2 2 1 1 1

nzvals(a) <- log1p(nzvals(a))
a
#> , , 1
#> 
#>           [,1] [,2]     [,3] [,4]      [,5]      [,6]      [,7]      [,8] [,9]
#> [1,] 0.0000000    0 0.000000    0 1.0986123 0.0000000 0.0000000 1.0986123    0
#> [2,] 0.6931472    0 0.000000    0 0.0000000 0.6931472 0.0000000 0.0000000    0
#> [3,] 0.0000000    0 0.000000    0 0.6931472 0.6931472 0.0000000 0.0000000    0
#> [4,] 0.0000000    0 0.000000    0 0.0000000 0.0000000 0.6931472 0.0000000    0
#> [5,] 0.0000000    0 1.098612    0 0.0000000 0.0000000 0.0000000 0.6931472    0
#>          [,10]     [,11]     [,12]
#> [1,] 0.0000000 0.0000000 0.0000000
#> [2,] 0.0000000 0.0000000 0.0000000
#> [3,] 0.0000000 0.6931472 0.0000000
#> [4,] 0.6931472 0.0000000 1.0986123
#> [5,] 0.0000000 0.6931472 0.6931472
#> 
#> , , 2
#> 
#>           [,1]      [,2]      [,3] [,4] [,5] [,6]      [,7]      [,8]      [,9]
#> [1,] 0.0000000 0.6931472 0.0000000    0    0    0 0.0000000 0.0000000 0.0000000
#> [2,] 0.6931472 0.0000000 0.6931472    0    0    0 0.6931472 0.6931472 0.0000000
#> [3,] 0.0000000 0.0000000 0.6931472    0    0    0 0.0000000 0.0000000 0.6931472
#> [4,] 0.0000000 0.6931472 0.0000000    0    0    0 0.6931472 0.0000000 0.0000000
#> [5,] 0.6931472 0.0000000 0.0000000    0    0    0 0.0000000 0.6931472 0.0000000
#>          [,10]     [,11]     [,12]
#> [1,] 0.0000000 0.6931472 0.0000000
#> [2,] 0.0000000 0.0000000 0.0000000
#> [3,] 0.0000000 0.0000000 0.6931472
#> [4,] 0.6931472 0.0000000 0.0000000
#> [5,] 0.0000000 0.0000000 0.0000000
#> 

## Sanity checks:
stopifnot(
  identical(nzidx, which(a != 0)),
  identical(Mnzidx, which(a != 0, arr.ind=TRUE, useNames=FALSE)),
  identical(nzvals(a), a[nzidx]),
  identical(nzvals(a), a[Mnzidx]),
  identical(`nzvals<-`(a, nzvals(a)), a)
)