eold - 13 days ago 4
R Question

How to apply function over each matrix element's indices

I am wondering if there is a built-in function in R which applies a function to each element of the matrix (of course, the function should be computed based on matrix indices). The equivalent would be something like this:

``````matrix_apply <- function(m, f) {
m2 <- m
for (r in seq(nrow(m2)))
for (c in seq(ncol(m2)))
m2[[r, c]] <- f(r, c)
return(m2)
}
``````

If there is no such built-in function, what is the best way to initialize a matrix to contain values obtained by computing an arbitrary function which has matrix indices as parameters?

I suspect you want `outer`:

``````> mat <- matrix(NA, nrow=5, ncol=3)

> outer(1:nrow(mat), 1:ncol(mat) , FUN="*")
[,1] [,2] [,3]
[1,]    1    2    3
[2,]    2    4    6
[3,]    3    6    9
[4,]    4    8   12
[5,]    5   10   15

> outer(1:nrow(mat), 1:ncol(mat) , FUN=function(r,c) log(r+c) )
[,1]     [,2]     [,3]
[1,] 0.6931472 1.098612 1.386294
[2,] 1.0986123 1.386294 1.609438
[3,] 1.3862944 1.609438 1.791759
[4,] 1.6094379 1.791759 1.945910
[5,] 1.7917595 1.945910 2.079442
``````

That yields a nice compact output. but it's possible that `mapply` would be useful in other situations. It is helpful to think of `mapply` as just another way to do the same operation that others on this page are using `Vectorize` for. `mapply` is more general because of the inability `Vectorize` to use "primitive" functions.

``````data.frame(mrow=c(row(mat)),   # straightens out the arguments
mcol=c(col(mat)),
m.f.res= mapply(function(r,c) log(r+c), row(mat), col(mat)  ) )
#   mrow mcol   m.f.res
1     1    1 0.6931472
2     2    1 1.0986123
3     3    1 1.3862944
4     4    1 1.6094379
5     5    1 1.7917595
6     1    2 1.0986123
7     2    2 1.3862944
8     3    2 1.6094379
9     4    2 1.7917595
10    5    2 1.9459101
11    1    3 1.3862944
12    2    3 1.6094379
13    3    3 1.7917595
14    4    3 1.9459101
15    5    3 2.0794415
``````

You probably didn't really mean to supply to the function what the row() and col() functions would have returned: This produces an array of 15 (somewhat redundant) 3 x 5 matrices:

``````> outer(row(mat), col(mat) , FUN=function(r,c) log(r+c) )
``````