acast

Simple and Fast Casting/Pivoting of an Array

Description

The acast() function spreads subsets of an array margin over a new dimension.
Written in ‘C’ and ‘C++’ for high speed and memory efficiency.

Roughly speaking, acast() can be thought of as the "array" analogy to data.table::dcast().
But note 2 important differences:

  • acast() works on arrays instead of data.tables.

  • acast() casts into a completely new dimension (namely ndim(x) + 1), instead of casting into new columns.

Usage

acast(x, ...)

## Default S3 method:
acast(
  x,
  margin,
  grp,
  fill = FALSE,
  fill_val = if (is.atomic(x)) NA else list(NULL),
  ...
)

Arguments

x an atomic or recursive array.
further arguments passed to or from methods.

margin a scalar integer, specifying the margin to cast from.
grp a factor, where length(grp) == dim(x)[margin], with at least 2 unique values, specifying which indices of dim(x)[margin] belong to which group.
Each group will be cast onto a separate index of dimension ndim(x) + 1.
Unused levels of grp will be dropped.
Any NA values or levels found in grp will result in an error.
fill Boolean.
When factor grp is unbalanced (i.e. has unequally sized groups) the result will be an array where some slices have missing values, which need to be filled. If fill = TRUE, an unbalanced grp factor is allowed, and missing values will be filled with fill_val.
If fill = FALSE (default), an unbalanced grp factor is not allowed, and providing an unbalanced factor for grp produces an error.
When x has type of raw, unbalanced grp is never allowed.
fill_val scalar of the same type of x, giving value to use to fill in the gaps when fill = TRUE.
The fill_val argument is ignored when fill = FALSE or when x has type of raw.

Details

For the sake of illustration, consider a matrix x and a grouping factor grp.
Let the integer scalar k represent a group in grp, such that k \(\in\) 1:nlevels(grp).
Then the code
out <- acast(x, margin = 1, grp = grp)
essentially performs the following for every group k:

  • copy-paste the subset x[grp == k, ] to the subset out[, , k].

Please see the examples section to get a good idea on how this function casts an array.
A more detailed explanation of the acast() function can be found on the website.

Value

An array with the following properties:

  • the number of dimensions of the output array is equal to ndim(x) + 1;

  • the dimensions of the output array is equal to c(dim(x), max(tabulate(grp));

  • the dimnames of the output array is equal to c(dimnames(x), list(levels(grp))).

Back transformation

From the casted array,
out = acast(x, margin, grp),
one can get the original x back by using
back = asplit(out, ndim(out)) |> bind_array(along = margin).
Note, however, the following about the back-transformed array back:

  • back will be ordered by grp along dimension margin;

  • if the levels of grp did not have equal frequencies, then dim(back)[margin] > dim(x)[margin], and back will have more missing values than x.

Examples

library("broadcast")


x <- cbind(id = c(rep(1:3, each = 2), 1), grp = c(rep(1:2, 3), 2), val = rnorm(7))
print(x)
##      id grp         val
## [1,]  1   1  0.33536503
## [2,]  1   2 -0.85234166
## [3,]  2   1  2.05957439
## [4,]  2   2 -0.88112227
## [5,]  3   1 -0.43829252
## [6,]  3   2 -0.70461364
## [7,]  1   2 -0.02925833

grp <- as.factor(x[, 2])
levels(grp) <- c("a", "b")
margin <- 1L

acast(x, margin, grp, fill = TRUE)
## , , a
## 
##      id grp        val
## [1,]  1   1  0.3353650
## [2,]  2   1  2.0595744
## [3,]  3   1 -0.4382925
## [4,] NA  NA         NA
## 
## , , b
## 
##      id grp         val
## [1,]  1   2 -0.85234166
## [2,]  2   2 -0.88112227
## [3,]  3   2 -0.70461364
## [4,]  1   2 -0.02925833