Museful
Museful

Reputation: 6959

Padding or shifting a multi-dimensional array

How can I simply pad (append/prepend) a slice of NA's to a (say) 3D array along (say) dimension 2?

Suppose the initial array is given as

A <- array(1:8,c(2,2,2))

I initially thought this would work:

cbind(A,NA)

but it results in an 8x2 matrix instead of a 2x3x2 array. I then tried

abind(A,NA,along=2)

but that results in an error.

I'm hoping there is a much simpler solution than

dimSlice <- dim(A)
dimSlice[2] <- 1
abind(A,array(NA,dimSlice),along=2)

Background

This padding happens as part of a "remove slice and pad opposite side" operation that shifts an array by one position along some dimension, filling in with NA elements at the vacated positions. The one-dimensional equivalent would be, for example, c(A[-1],NA) for vector A, If there is a simple way to accomplish such an operation without an explicit padding sub-operation, that would be even better.

Upvotes: 2

Views: 556

Answers (1)

alexis_laz
alexis_laz

Reputation: 13122

Subsetting with NAs results in NAs (?Extract):

v = 1:3; m = matrix(1:4, 2, 2); a = array(1:6, c(2, 2, 2))
v[c(NA, 1)]
#[1] NA  1
m[, c(2, NA)]
#     [,1] [,2]
#[1,]    3   NA
#[2,]    4   NA
a[, c(1, 2, NA), ]
#, , 1
#
#     [,1] [,2] [,3]
#[1,]    1    3   NA
#[2,]    2    4   NA
#
#, , 2
#
#     [,1] [,2] [,3]
#[1,]    5    1   NA
#[2,]    6    2   NA

So, to pad with NAs, we could subset using the appropriate indices. Putting the above in a more general function to append/prepend "n" indices with NA in dimension "k" of an array:

pad = function(x, k, n = 1L, append = TRUE)
{
    dims = replicate(length(dim(x)), substitute(), simplify = FALSE)
    if(append) dims[[k]] = c((n + 1):dim(x)[[k]], rep_len(NA, n))
    else dims[[k]] = c(rep_len(NA, n), 1:(dim(x)[[k]] - n))
    do.call("[", c(list(x), dims))
}

arr = array(1:24, c(3, 2, 2, 2))
pad(arr, 1, 2, FALSE)
pad(arr, 2)

Upvotes: 2

Related Questions