Barbara
Barbara

Reputation: 188

Using a 2D array as an index to a 3D array

I have a three-dimensional array in R, e.g.

a <- array(1:24, dim=c(2,3,4))

I'll refer to the dimensions of this array as rows, columns and layers. I have a second variable, b, which is intended to provide an index to that array, e.g.

b <- array(c(1,4,3,2,2,1), dim=c(2,3))

I would like to get a two-dimensional variable, d that contains the value from 3D variable a in the layer specified by b for each row and column in a and b. So for example, d[1, 1] <- a[1, 1 , b[1, 1]] and d[2, 3] <- a[2, 3, b[2, 3]] and so on. In this example, I should end up with:

 d == array(c(1, 20, 15, 10, 11, 6), dim=c(2, 3))

What's the most efficient way to do this?

Upvotes: 0

Views: 388

Answers (3)

Onyambu
Onyambu

Reputation: 79288

The fastest way you can do this:

structure(a[cbind(c(row(b)),c(col(b)),c(b))],.Dim=dim(b))
     [,1] [,2] [,3]
[1,]    1   15   11
[2,]   20   10    6

Upvotes: 2

Tom
Tom

Reputation: 1138

I'd suggest using expand.grid as well, but I would generate an index matrix to adress every entry of a at once.

ind <- as.matrix(expand.grid(1:nrow(b), 1:ncol(b)))
d <- matrix(a[cbind(ind, b[ind])], ncol = ncol(b), nrow = nrow(b))

I think this is slightly more efficient

Upvotes: 1

Ronak Shah
Ronak Shah

Reputation: 389105

We can use expand.grid to get all combinations of rows and columns in b and then use mapply to get the corresponding output from a using indexing. We use relist to make the d matrix same as b.

df <- expand.grid(row = 1:nrow(b), col = 1:ncol(b))
d <- relist(mapply(function(x, y) a[x, y, b[x, y]], df$row, df$col), b)
d

#     [,1] [,2] [,3]
#[1,]    1   15   11
#[2,]   20   10    6

where df is

   row col
#1   1   1
#2   2   1
#3   1   2
#4   2   2
#5   1   3
#6   2   3

Upvotes: 1

Related Questions