[R] How to select multiple cells in a matrix and perform an operation on corresponding cells in another matrix of the same size?

Jim Lemon jim at bitwrit.com.au
Tue Mar 25 21:41:26 CET 2014


On 03/25/2014 11:36 PM, Vermeulen, Lucie wrote:
> Hi Jim,
>
> Thanks for your help! I tried it on my own data, but there seems to be a problem with NA values. For regions where there is no flow or pollutant, my cells are NA. Using your script below changed to include NA's in flowmat, I get the error message "Error in if (selected_cells[row, col]) { :   missing value where TRUE/FALSE needed"
>
> I tried several things to solve this, indicated below in the script, but none of them work. Do you perhaps know a solution to this?
> Lucie
>
Hi Lucie,
If you want to test for NA in a conditional statement, put that test 
last, as it will be evaluated first. Of course the operator must be AND 
(&&) or it won't work.

# assume three flow rates
flowmat<-matrix(sample(c(1,2,3,NA),100,TRUE),nrow=10)
# directions are 1 to 8 starting at North and going clockwise
dirmat<-matrix(sample(1:8,100,TRUE),nrow=10)
# some values for pollutant concentration (?)
pollmat<-matrix(runif(100),nrow=10)
dimmat<-dim(flowmat)
# these translate the "direction" value into row and column changes
rowdirs<-c(0,1,1,1,0,-1,-1,-1)
coldirs<-c(1,1,0,-1,-1,-1,0,1)
# the matrix to be updated
newpollmat<-matrix(0,nrow=dimmat[1],ncol=dimmat[2])
for(flow in unique(flowmat)) {
  # this yields a matrix where all cells of a given flow are TRUE
  selected_cells<-flowmat == flow
  for(row in 1:dimmat[1]) {
   for(col in 1:dimmat[2]) {
    # only update the selected cells - note the extra test for NA
    if(selected_cells[row,col] && !is.na(selected_cells[row,col])) {
     newrow<-row+rowdirs[dirmat[row,col]]
     newcol<-col+coldirs[dirmat[row,col]]
     # don't go out of the matrix
     if(newrow >= 1 && newrow <= 10 && newcol >= 1 && newcol <= 10)
      # update the new pollutant matrix
      newpollmat[newrow,newcol]<-pollmat[row,col]*flowmat[row,col]
    }
   }
  }
}

Also, if you want to wrap your matrix, you can use something like this:

     newrow<-row+rowdirs[dirmat[row,col]]%%10
     newcol<-col+coldirs[dirmat[row,col]]%%10

Jim




More information about the R-help mailing list