13

Possible Duplicate:
Sum a list of matrices
Add together a list of matrices element-by-element

I have a R list object. Each element of the list contains 3 by 3 matrix. I want to sum all the matrices element-wise. That is:

 myList <- list();
 myList[[1]] <- matrix(1:9,3,3)
 myList[[2]] <- matrix((1:9)*10,3,3)

Then I want the final output output

myList[[1]]+myList[[2]]

      [,1] [,2] [,3]
 [1,]   11   44   77
 [2,]   22   55   88
 [3,]   33   66   99

Of course I can write a loop for this calculation but loop in R is very slow. Is there built in function in R which does this business?

Community
  • 1
  • 1
FairyOnIce
  • 2,526
  • 7
  • 27
  • 48
  • 1
    Premature optimization is the root of all evil. Unless you have evidence that this operation is likely to be the performance bottleneck of whatever program you're writing, then does it make a significant difference whether you loop through the matrices or not? –  Jan 03 '13 at 21:37

4 Answers4

24

See ?Reduce.

From the example:

## A general-purpose adder:
add <- function(x) Reduce("+", x)

Then you can

add(myList)
GSee
  • 48,880
  • 13
  • 125
  • 145
6

Alternatively, you could put the data in a multi-dimensional array instead of a list, and use apply on that.

require(abind)
m = abind(matrix(1:9,3,3), matrix((1:9)*10,3,3), along = 3)

yields a three dimensional array. Then use apply:

apply(m, 1:2, sum)

Disclaimer: I did not test this code as I do not have R available right now. However, I do wanted you to be aware of this option.

Paul Hiemstra
  • 59,984
  • 12
  • 142
  • 149
  • +1 for `abind`, although the call is wrong. Should instead be `apply(m, 1:2, sum)` – IRTFM Jan 04 '13 at 00:28
  • 1
    Exactly. Lists are excellent for organizing data of different types or classes or sizes, but when you've got a bunch of well-organized matrices, stick with tensors (the math term for n-rank data). – Carl Witthoft Jan 04 '13 at 12:55
3

For those interested:

ffoo<-function(jloop){
barlist<-matrix(nr=25,nc=40)
for (jj in 1:jloop) barlist<-barlist+foolist[[jj]]
}

baradd <- function(x) Reduce("+", x)

Leads to:

Rgames> foo<-matrix(1:1000,25)
Rgames> for (jj in 1:5e5) foolist[[jj]]<-foo
Rgames> system.time(baradd(foolist))
   user  system elapsed 
    1.7     0.0     1.7 

Rgames> system.time(ffoo(1e5))
   user  system elapsed 
    0.3     0.0     0.3
Carl Witthoft
  • 20,573
  • 9
  • 43
  • 73
2
> do.call("+", myList)
     [,1] [,2] [,3]
[1,]   11   44   77
[2,]   22   55   88
[3,]   33   66   99

But it fails for more than two which I why I upvoted GSee's answer.

IRTFM
  • 258,963
  • 21
  • 364
  • 487