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?
This does not answer your question exactly, but I found it while trying to figure out a similar question so I'll show you something.
Say you have a function which you want to apply to each element of a matrix which requires just one part.
And say you have a matrix X,
then you do this:
Then it will do an element-wise double of each value.
However, if you do logic in the function like below you will get a warning that it is not parameterized and not behave as you expect.
But if you use the apply() function you can use it.
For example:
So that is great, right? Well, it breaks down if you have a function with two or more parms. Say for example you have this:
In this case, you use the apply() function. However, it will lose the matrix but the results are calculated correctly. They can be reformed if you are so inclined.
I suspect you want
outer
:That yields a nice compact output. but it's possible that
mapply
would be useful in other situations. It is helpful to think ofmapply
as just another way to do the same operation that others on this page are usingVectorize
for.mapply
is more general because of the inabilityVectorize
to use "primitive" functions.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:
You didn't tell us what kind of function you want to apply to each element, but I think that the only reason the examples in the other answers work is because the functions are already vectorized. If you really want to apply a function to each element,
outer
will not give you anything special that the function didn't already give you. You'll notice that the answers didn't even pass a matrix toouter
!How about following @Chase's comment and use
apply
.For example, I have the matrix
If I want to turn it into a character matrix, element by element (just as an example) I could do this
Of course,
as.character
is already vectorized, but my special functionmy.special.function
isn't. It only takes one argument, an element. There is no straighforward way to getouter
to work with it. But, this worksYou may be thinking of
outer
:That's clearly a fairly trivial example function, but you can supply your own custom one as well. See
?outer
.Edit
Contrary to the comment below, you can also use
outer
with non-vectorized functions by....vectorizing them!The simplest approach is just to use an
f()
that can be applied directly to the elements of the matrix. For example, using the matrixm
from @adamleerich's AnswerThere is no reason to use
apply()
in the case of theas.character()
example. Instead we can operate on the elements ofm
as if it were a vector (it really is one) and replace in-place:The first part of that block is the key here.
m[]
forces the elements ofm
to be replaced by the output fromas.character()
, rather than overwritingm
with a vector of characters.So that is the general solution to applying a function to each element of a matrix.
If one really needs to use an
f()
that works on row and column indices then I'd write af()
usingrow()
andcol()
:or one that use
outer()
as other's have shown. Iff()
isn't vectorised, then I'd rethink my strategy as far as possible as there i) probably is a way to write a truly vectorised version, and ii) a function that isn't vectorised isn't going to scale very well.