Filling a matrix efficiently in R based on row and column indices

I am filling a matrix in R, and the most(?) intuitive way to do this is to use two nested loops: one for rows and one for columns. However, this method tends to be quite slow, and the use of apply() function is usually preferable.

Everything would be easy with apply, if I was just transforming the existing values of my matrix with some function, but I am actually using an external function which takes the row and column indices as arguments and returns a value.

The function could be something like this (just an example):

myfunction <- function(rownumber, colnumber) {
                       if(rownumber + colnumber < 7) {
                          return(4)
                       } else {
                          return(2)
                       }
}

...and with two nested loops we could proceed like this:

m <- matrix(0, nrow = 5, ncol = 5)

for(rownum in 1:nrow(m)) {
    for(colnum in 1:ncol(m)) {
        m[rownum, colnum] <- myfunction(rownum, colnum)
    }
}

And something like this comes out:

> m
     [,1] [,2] [,3] [,4] [,5]
[1,]    4    4    4    4    4
[2,]    4    4    4    4    2
[3,]    4    4    4    2    2
[4,]    4    4    2    2    2
[5,]    4    2    2    2    2

I would like to use apply() function for this, since it is generally faster than two nested loops, but I have no idea, how to get row number and column number - or if that's even possible? One solution would be to save the row numbers and col numbers initially to the matrix as STRINGS, but again this would take some time, since it needs to be done with two nested loops...

Any ideas? Thanks.

Upvotes: 1

Views: 1058

Answers (2)

SmokeyShakers
SmokeyShakers

Reputation: 3402

outer should accomplish what you need

First, make sure your function can work vectorized:

myfunction <- function(rownumber, colnumber) {
     ifelse(rownumber + colnumber < 7,4,2) # ifelse is vectorized
 }

Then

outer(0:5, 0:5, FUN = myfunction)

Upvotes: 1

St&#233;phane Laurent
St&#233;phane Laurent

Reputation: 84649

If your function is efficiently vectorized, you can do a matrix of row indices and a matrix of column indices as follows:

rownumbers <- matrix(1:4, nrow = 4, ncol = 3)
#      [,1] [,2] [,3]
# [1,]    1    1    1
# [2,]    2    2    2
# [3,]    3    3    3
# [4,]    4    4    4
colnumbers <- t(matrix(1:4, nrow = 4, ncol = 4))[, 1:3]
#      [,1] [,2] [,3]
# [1,]    1    2    3
# [2,]    1    2    3
# [3,]    1    2    3
# [4,]    1    2    3

Then do f(rownumbers, colnumbers).


EDIT

I've just discovered the functions col and row. It's easier to use these functions to construct the two matrices.

Upvotes: 1

Related Questions