So I want to apply a function over a matrix in R. This works really intuitively for simple functions:
> (function(x)x*x)(matrix(1:10, nrow=2))
[,1] [,2] [,3] [,4] [,5]
[1,] 1 9 25 49 81
[2,] 4 16 36 64 100
…but clearly I don’t understand all of its workings:
> m = (matrix(1:10, nrow=2))
> (function(x) if (x %% 3 == 0) { return(NA) } else { return(x+1) })(m)
[,1] [,2] [,3] [,4] [,5]
[1,] 2 4 6 8 10
[2,] 3 5 7 9 11
Warning message:
In if (x == 3) { :
the condition has length > 1 and only the first element will be used
I read up on this and found out about Vectorize and sapply, which both seemed great and just like what I wanted, except that both of them convert my matrix into a list:
> y = (function(x) if (x %% 3 == 0) { return(NA) } else { return(x+1) })
> sapply(m, y)
[1] 2 3 NA 5 6 NA 8 9 NA 11
> Vectorize(y)(m)
[1] 2 3 NA 5 6 NA 8 9 NA 11
…whereas I’d like to keep it in a matrix with its current dimensions. How might I do this? Thanks!
@Joshua Ulrich (and Dason) has a great answer. And doing it directly without the function
yis the best solution. But if you really need to call a function, you can make it faster usingvapply. It produces a vector without dimensions (assapply, but faster), but then you can add them back usingstructure:…As you can see, the
vapplyapproach is about 3x faster thanapply… And the reasonvapplyis faster thansapplyis thatsapplymust analyse the result to figure out that it can be simplified to a numeric vector. Withvapply, you specified the result type (numeric(1)), so it doesn’t have to guess…UPDATE I figured out another (shorter) way of preserving the matrix structure:
You simply assign the new values to the object using
m[] <-. Then all other attributes are preserved (likedim,dimnames,classetc).