2015-06-20 35 views
0

我有两个2x2矩阵数组,我想在每对2x2矩阵上应用一个函数。这里有一个最小的例如,通过其相应的矩阵中B在A中的每个矩阵乘以:在多个数组上应用R函数,返回相同大小的数组

A <- array(1:20, c(5,2,2)) 
B <- array(1:20, c(5,2,2)) 
n <- nrow(A) 
# Desired output: array with dimension 5x2x2 that contains 
# the product of each pair of 2x2 matrices in A and B. 
C <- aperm(sapply(1:n, function(i) A[i,,]%*%B[i,,], simplify="array"), c(3,1,2)) 

这需要两个阵列,每个具有5点2×2矩阵,和乘以每对2×2的矩阵一起,在C所期望的结果。

我现在的代码是这个丑陋的最后一行,使用sapply循环遍历第一个数组维度,并从A和B分别拉出每个2x2矩阵。然后我需要用aperm()按顺序排列数组维度具有与原始数组相同的顺序(sapply(...,simplify =“array”)使用第三维索引每个2×2矩阵,而不是第一维)。

有没有更好的方法来做到这一点?我讨厌那个丑陋的函数(i),这实际上只是伪造for循环的一种方式。而aperm()调用使得这种可读性更低。我现在工作的很好;我只是寻找感觉更像惯用的东西。

mapply()将采用多个列表或向量,但它似乎不适用于数组。来自plyr的aaply()也接近,但它不需要多个输入。我最近来的是使用abind()和aaply()将A和B一起打包成一个有2个矩阵的数组,但这不起作用(它只获取前两个条目;某处我的索引是关闭的):

aaply(.data=abind(A,B,along=0), 1, function(ab) ab[1,,]%*%ab[2,,]) 

而且这不完全清洁或无论如何更清晰!我试图让这个最小的例子,但我真正的用例需要一个更复杂的矩阵对功能(我也喜欢扩大到两个以上的数组),所以我'我正在寻找可以推广和扩展的东西。

回答

1

有时for循环是最容易遵循的。它还概括和规模:

n <- nrow(A) 
C <- A 
for(i in 1:n) C[i,,] <- A[i,,] %*% B[i,,] 
+0

是的,我应该提到这是另一个明显的解决方案。我希望有一个功能性的方法,但R似乎没有使用数组做功能性事务的基础结构比使用列表更少。我想避免循环使A和B的表达更复杂,所以我没有全部索引。 – cauchy

+0

没有太多的可读性损失,你可以在RcppArmadillo中编写这个循环,它非常类似于矩阵代数和索引的R/matlab。 – baptiste

+1

循环应该和'sapply'一样好。我已经看到循环是最快解决方案的情况。它很容易将索引隐藏在函数中:'combine < - function(A,B,FUN ='%*%'){...}'如果您担心速度,那么将5维放在末尾的开始。而不是使用数组,你可以使用矩阵列表。 –

0

的r的名单基础设施要好得多(似乎)是通过对数组,所以我也可以通过转换阵列成矩阵的名单像这样来解决:

A <- alply(A, 1, function(a) matrix(a, ncol=2, nrow=2)) 
B <- alply(A, 1, function(a) matrix(a, ncol=2, nrow=2)) 
mapply(function(a,b) a%*%b, A, B, SIMPLIFY=FALSE) 

我认为这比我上面的更直接,但我仍然喜欢听到更好的想法。

2
D <- aaply(abind(A, B, along = 4), 1, function(x) x[,,1] %*% x[,,2]) 

这是使用abindaaply的工作溶液。