tags:

views:

114

answers:

1

I understand how outer() works in R:

> outer(c(1,2,4),c(8,16,32), "*")

     [,1] [,2] [,3]
[1,]    8   16   32
[2,]   16   32   64
[3,]   32   64  128

It basically takes 2 vectors, finds the crossproduct of those vectors, and then applies the function to each pair in the crossproduct.

I don't have two vectors, however. I have two lists of matrices:

M = list();

M[[1]] = matrix(...)
M[[2]] = matrix(...)
M[[3]] = matrix(...)

And I want to do an operation on my list of matricies. I want to do:

outer(M, M, "*")

In this case, I want to take the dot product of each combination of matrices I have.

Actually, I am trying to generate a kernel matrix (and I have written a kernel function), so I want to do:

outer(M, M, kernelFunction)

where kernelFunction calculates a distance between my two matrices.

The problem is that outer() only takes "vector" arguments, rather than "list"s etc. Is there a function that does the equivalent of outer() for non-vector entities?

Alternately, I could use a for-loop to do this:

M = list() # Each element in M is a matrix

for (i in 1:numElements)
{
   for (j in 1:numElements)
   {
      k = kernelFunction(M[[i]], M[[j]])
      kernelMatrix[i,j] = k;
   }
}

but I am trying to avoid this in favor of an R construct (which might be more efficient). (Yes I know I can modify the for-loop to compute the diagonal matrix and save 50% of the computations. But that's not the code that I'm trying to optimize!)

Is this possible? Any thoughts/suggestions?

+5  A: 

Just use the for loop. Any built-in functions will degenerate to that anyway, and you'll lose clarity of expression, unless you carefully build a function that generalises outer to work with lists.

The biggest improvement you could make would be to preallocate the matrix:

M <- list()
length(M) <- numElements ^ 2
dim(M) <- c(numElements, numElements)

PS. A list is a vector.

hadley