Reputation: 13113
I would like to average elements in a 3-dimensional array among groups of sheets or pages (my name for the third dimension).
Below is an example array called my.array
. In this example I want to average elements among groups of 3 sheets giving the desired.result
. My actual data is in an array with dozens of sheets.
I suspect there is an apply
-like function that can do the averaging. However, I am not familiar with using those functions on arrays. Thank you for any advice.
i <- 4
j <- 4
k <- 6
my.array <- array(0, c(i,j,k))
my.array[1:2,1:2,1] <- 1
my.array[1:2,3:4,1] <- 2
my.array[3:4,1:2,1] <- 3
my.array[3:4,3:4,1] <- 4
my.array[1:2,1:2,2] <- 10
my.array[1:2,3:4,2] <- 20
my.array[3:4,1:2,2] <- 30
my.array[3:4,3:4,2] <- 40
my.array[1:2,1:2,3] <- 100
my.array[1:2,3:4,3] <- 200
my.array[3:4,1:2,3] <- 300
my.array[3:4,3:4,3] <- 400
my.array[1:2,1:2,4] <- -4
my.array[1:2,3:4,4] <- -3
my.array[3:4,1:2,4] <- -2
my.array[3:4,3:4,4] <- -1
my.array[1:2,1:2,5] <- 80
my.array[1:2,3:4,5] <- 70
my.array[3:4,1:2,5] <- 60
my.array[3:4,3:4,5] <- 50
my.array[1:2,1:2,6] <- 111
my.array[1:2,3:4,6] <- 222
my.array[3:4,1:2,6] <- 333
my.array[3:4,3:4,6] <- 444
desired.result <- array(0, c(i,j,k/3))
desired.result[1:2,1:2,1] <- 37 # 111 / 3
desired.result[1:2,3:4,1] <- 74 # 222 / 3
desired.result[3:4,1:2,1] <- 111 # 333 / 3
desired.result[3:4,3:4,1] <- 148 # 444 / 3
desired.result[1:2,1:2,2] <- 62.33333 # (111 + 80 + -4) / 3
desired.result[1:2,3:4,2] <- 96.33333 # (222 + 70 + -3) / 3
desired.result[3:4,1:2,2] <- 130.3333 # (333 + 60 + -2) / 3
desired.result[3:4,3:4,2] <- 164.3333 # (444 + 50 + -1) / 3
, , 1
[,1] [,2] [,3] [,4]
[1,] 37 37 74 74
[2,] 37 37 74 74
[3,] 111 111 148 148
[4,] 111 111 148 148
, , 2
[,1] [,2] [,3] [,4]
[1,] 62.33333 62.33333 96.33333 96.33333
[2,] 62.33333 62.33333 96.33333 96.33333
[3,] 130.33330 130.33330 164.33330 164.33330
[4,] 130.33330 130.33330 164.33330 164.33330
This code comes close:
t(sapply(seq(1,2), function(i) {apply( my.array[,,(3*(i-1)+1):(3*i)], c(1,2), mean)}))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15] [,16]
[1,] 37.00000 37.00000 111.0000 111.0000 37.00000 37.00000 111.0000 111.0000 74.00000 74.00000 148.0000 148.0000 74.00000 74.00000 148.0000 148.0000
[2,] 62.33333 62.33333 130.3333 130.3333 62.33333 62.33333 130.3333 130.3333 96.33333 96.33333 164.3333 164.3333 96.33333 96.33333 164.3333 164.3333
I prefer a solution in base R.
Upvotes: 1
Views: 92
Reputation: 99351
What about just wrapping the sapply
call with the desired array? It uses only base R functions.
> array(sapply(seq(1,2), function(i) {
apply( my.array[,,(3*(i-1)+1):(3*i)], c(1,2), mean)
}), c(i,j,k/3))
Upvotes: 1
Reputation: 2818
one possibility is to use a factor that will identify the group of "sheets" and use the abind fonction from the package abind :
res <- tapply(1:(dim(my.array)[3]), gl(2,3), function(x) rowMeans(my.array[,,x], dim=2))
res <- do.call(abind, c(res, along=3))
HTH
Upvotes: 1