2015-06-20 65 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的工作溶液。