1

Is there a way of elegantly specify a slice in a multidimensional array in R, whereby the number of dimensions is not known beforehand?

For instance, for a 5-dimensional array, slicing out the last dimension can be done using

fourdimslice <- fivedimarray[,,,,1]

but I'l like to code this for arbitrary dimensions, something like

slice <- arbitrarydimarray(dim=5, index=1)

I've not been able to understand if do.call('[', ...) would be an approach. I've also tried named dimensions, but a[fifth=1] is not interpreted the way I would want here.

I suppose functions like apply() need to do similar things.

davidav
  • 860
  • 8
  • 12
  • 2
    See if http://stackoverflow.com/questions/14500707/select-along-one-of-n-dimensions-in-array/14501461#14501461 answers your question. – flodel May 17 '13 at 11:04
  • I actually wrote some code once (when young and foolish :-) ) which looked at the number of dimensions of an array and built a string by looping on something like `foo<-'x[' ; for (i in 1:(n-1) ) foo <- paste(foo,',') ` . V. Zoonekynd's answer is very nice indeed. – Carl Witthoft May 17 '13 at 11:25

3 Answers3

5

You can use asub, from the abind package.

# Sample data: a 5-dimensional array
x <- array(seq_len(prod(2:6)), dim=2:6)

library(abind)
str( asub(x, 1, 5) )
# int [1:2, 1:3, 1:4, 1:5] 1 2 3 4 5 6 7 8 9 10 ...
str( x[,,,,1] )
# int [1:2, 1:3, 1:4, 1:5] 1 2 3 4 5 6 7 8 9 10 ...
all( asub(x, 1, 5) == x[,,,,1] )
# [1] TRUE
Vincent Zoonekynd
  • 31,893
  • 5
  • 69
  • 78
2

If you don't want to use the abind package, it looks like you can use a two-liner based on slice.index. I don't know which is more efficient ...

x <- array(seq_len(prod(2:6)), dim=2:6)
library(abind)
str( y <- asub(x, 1, 5) )

Or:

z <- x[slice.index(x,5)==1]

This extracts the right elements but the dimensions get lost. To restore them:

dim(z) <- dim(x)[-5]

(You could obviously wrap this in an appropriate function.) Test:

all.equal(y,z)  ## TRUE
Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
0

Here is a bizarre solution to extract the first slice

your.array=array(runif(27),dim=c(3,3,3)) # this is to create an example of array from which you want a slice.

array(your.array[1:prod(dim(your.array)[-1])],dim(your.array)[-1])
Remi.b
  • 17,389
  • 28
  • 87
  • 168