acast

Simple and Fast Casting/Pivoting of an Array

Description

The acast() function spreads subsets of an array margin over a new dimension.

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, ...)

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.
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.
If fill_val is missing, it is specified as follows:

  • If x is of type raw and fill = TRUE, fill_val is not allowed to be missing, and an error is returned;

  • If x is atomic but not raw, fill_val is set to NA;

  • If x is of type list, fill_val is set to list(NULL).

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.

Value

An array with dimensions c(dim(x), max(tabulate(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.

See Also

broadcast_casting

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.02394361
## [2,]  1   2  1.09561230
## [3,]  2   1 -0.56826535
## [4,]  2   2  0.97642221
## [5,]  3   1 -0.76407003
## [6,]  3   2  1.69261292
## [7,]  1   2 -0.24632036

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.02394361
## [2,]  2   1 -0.56826535
## [3,]  3   1 -0.76407003
## [4,] NA  NA          NA
## 
## , , b
## 
##      id grp        val
## [1,]  1   2  1.0956123
## [2,]  2   2  0.9764222
## [3,]  3   2  1.6926129
## [4,]  1   2 -0.2463204