user3100267
user3100267

Reputation:

R's "apply" to a multi-dimensional array a function that itself return an array

I have a 3D array of dimensions MxNxO. For each of the M arrays of dimensions NxO, I want to apply a function myfunction that takes as input a NxO array and return a NxO array.

If I do

apply(array, 1, myfunction)

the output is a 2D array of dimension (N*O)xM instead of a 2D array of dimensions MxNxO.

As an example, we can use the identity function from R.

Here is a 3D array

> a <- array(1:20, c(2,2,5))
, , 1

     [,1] [,2]
[1,]    1    3
[2,]    2    4

, , 2

     [,1] [,2]
[1,]    5    7
[2,]    6    8

, , 3

     [,1] [,2]
[1,]    9   11
[2,]   10   12

, , 4

     [,1] [,2]
[1,]   13   15
[2,]   14   16

, , 5

     [,1] [,2]
[1,]   17   19
[2,]   18   20

and the apply result should be the same (for my needs) but it is a 2D array instead:

> apply(a,1,identity)
      [,1] [,2]
 [1,]    1    2
 [2,]    3    4
 [3,]    5    6
 [4,]    7    8
 [5,]    9   10
 [6,]   11   12
 [7,]   13   14
 [8,]   15   16
 [9,]   17   18
[10,]   19   20

Also, I would like to preserve the labels on each dimension of the array (myfunction itself preserves those labels).

Upvotes: 2

Views: 361

Answers (2)

BrodieG
BrodieG

Reputation: 52647

If you know the dimensions that your function will be returning (as you do in your trivial example), then you can us vapply. I also would have suggested aaply, though I prefer the result to be 2 2x5 matrices, not 5 2x2 matrices (since a[1, ,] is a 2x5 matrix, so this makes more sense to me).

dim <- c(x=2,y=2,z=5)
dim.n <- lapply(1:length(dim), function(x) paste(names(dim)[x], seq(len=dim[x]), sep="_"))
a <- array(1:20, dim, dim.n)
vapply(dimnames(a)[[1]], function(i) identity(a[i, ,]), a[1, ,])
# , , x_1
# 
#     z_1 z_2 z_3 z_4 z_5
# y_1   1   5   9  13  17
# y_2   3   7  11  15  19
# 
# , , x_2
# 
#     z_1 z_2 z_3 z_4 z_5
# y_1   2   6  10  14  18
# y_2   4   8  12  16  20

Main advantage of this is it's all base package, so you don't need to include plyr. The plyr answer is fine so long as you're okay with the interpretation of what the return dimensions should be, or don't necessarily know ahead of time the result format.

Also, I recognize the format here is nowhere near as clean as aaply, and wish apply respected the dimensions so one didn't need to resort to these things. I had a very similar question last week.

Upvotes: 0

joran
joran

Reputation: 173577

You are probably looking for aaply in the plyr package:

a <- array(1:20, c(2,2,5))
> aaply(a,1,identity)
, ,  = 1


X1  1 2
  1 1 3
  2 2 4

, ,  = 2


X1  1 2
  1 5 7
  2 6 8

, ,  = 3


X1   1  2
  1  9 11
  2 10 12

, ,  = 4


X1   1  2
  1 13 15
  2 14 16

, ,  = 5


X1   1  2
  1 17 19
  2 18 20

Upvotes: 2

Related Questions