将函数应用于3d数组的每个图层,返回一个数组

时间:2012-12-10 23:32:16

标签: r

想象一下,你有一个包含行,列和图层的三维数组:

A <- array (1:27, c(3,3,3))

并想象你有一个函数将矩阵作为输入并返回一个矩阵作为输出,如t

如何将函数应用于数组的每一层,返回与第一层相同大小的另一个数组?

我觉得我应该能够以apply的方式做到这一点,但我做不到。

奖金问题(如果你回答这个问题,我将非常感激):这样做是否更快,或者为每个层矩阵制作一个列表并将lapply函数添加到它们中?

-

编辑:请不要认为这个问题已经回答了 - 下面的答案没有回答这个问题。

2 个答案:

答案 0 :(得分:5)

您必须考虑要提取值的边距。

您可以通过应用维度1和2(行和列来换取更好的单词)来转置每个3rd维度矩阵

apply(A,1:2,t)
, , 1

     [,1] [,2] [,3]
[1,]    1    2    3
[2,]   10   11   12
[3,]   19   20   21

, , 2

     [,1] [,2] [,3]
[1,]    4    5    6
[2,]   13   14   15
[3,]   22   23   24

, , 3

     [,1] [,2] [,3]
[1,]    7    8    9
[2,]   16   17   18
[3,]   25   26   27

您还可以使用可能更直观的plyraaply

library(plyr)

aaply(A,3,t)
, ,  = 1


X1   1  2  3
  1  1  4  7
  2 10 13 16
  3 19 22 25

, ,  = 2


X1   1  2  3
  1  2  5  8
  2 11 14 17
  3 20 23 26

, ,  = 3


X1   1  2  3
  1  3  6  9
  2 12 15 18
  3 21 24 27

至于哪个更快lapplyapply,我想也许lapply会赢,但你仍然需要考虑你想要提取矩阵的边距从

我通常发现在一个维度上思考要容易得多。如果地球平坦,一切都会更直接!

答案 1 :(得分:1)

转置的另一种可能性是函数aperm

A <- array (1:27, c(3,3,3))
# aperm permute the dimensions in the given order
# here we want to permute dimension 1 and 2
# so the new order is 2-1-3 instead of 1-2-3
aperm(A, c(2,1,3)) 
    , , 1

     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9

, , 2

     [,1] [,2] [,3]
[1,]   10   11   12
[2,]   13   14   15
[3,]   16   17   18

, , 3

     [,1] [,2] [,3]
[1,]   19   20   21
[2,]   22   23   24
[3,]   25   26   27

就每个层应用一个函数(比如你想将每个层乘以不同的值)而言,这是另一种可能性:

vec <- c(1,5,3)
lapply(seq_along(vec), function(x)A[,,x]*vec[x])
[[1]]
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9

[[2]]
     [,1] [,2] [,3]
[1,]   50   65   80
[2,]   55   70   85
[3,]   60   75   90

[[3]]
     [,1] [,2] [,3]
[1,]   57   66   75
[2,]   60   69   78
[3,]   63   72   81

但是当你看到它创建一个列表时,它需要使用函数simplify2array再多一步:

simplify2array(lapply(seq_along(vec),function(x)A[,,x]*vec[x]))
, , 1

     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9

, , 2

     [,1] [,2] [,3]
[1,]   50   65   80
[2,]   55   70   85
[3,]   60   75   90

, , 3

     [,1] [,2] [,3]
[1,]   57   66   75
[2,]   60   69   78
[3,]   63   72   81

或直接使用sapply

sapply(seq_along(vec), function(x)A[,,x]*vec[x], simplify="array")
, , 1

     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9

, , 2

     [,1] [,2] [,3]
[1,]   50   65   80
[2,]   55   70   85
[3,]   60   75   90

, , 3

     [,1] [,2] [,3]
[1,]   57   66   75
[2,]   60   69   78
[3,]   63   72   81