Question

I have a matrix with either 1s or 0s.

xmat = matrix(round(runif(12),0), ncol=3)
     [,1] [,2] [,3]
[1,]    0    1    1
[2,]    1    0    1
[3,]    1    0    0
[4,]    1    0    1

I also have a rule table, which is a list.

a = c(0.2, 0.5)
b = c(0.5, 0.6)
c = c(0.8, 0.1)
names(a) = c("0", "1")
names(b) = c("0", "1")
names(c) = c("0", "1")

ruletable = list(a, b, c)

[[1]]
  0   1 
0.2 0.5 

[[2]]
  0   1 
 0.5 0.6 

[[3]]
  0   1 
 0.8 0.1 

I need to replace the 1s and 0s in each column of xmat with the corresponding values specified by the rule table. For example, the first column of xmat is (0, 1, 1, 1), which needs to be converted into (0.2, 0.5, 0.5, 0.5) using ruletable[[1]]. Similarly, the second column of xmat (1, 0, 0, 0) needs to be converted into (0.6, 0.5, 0.5, 0.5) using ruletable[[2]]. Since this is potentially a huge matrix, I am looking for a solution without using for loop.

Thanks!

Was it helpful?

Solution

This should be reasonably efficient:

vapply(
  1:length(ruletable), 
  function(x) ruletable[[x]][xmat[, x] + 1L],
  numeric(nrow(xmat))
)

original matrix (set.seed(1)):

#      [,1] [,2] [,3]
# [1,]    0    0    0
# [2,]    0    1    0
# [3,]    0    1    0
# [4,]    1    1    1  

and result:

#      [,1] [,2] [,3]
# [1,]  0.2  0.5  0.8
# [2,]  0.2  0.6  0.8
# [3,]  0.2  0.6  0.8
# [4,]  0.5  0.6  0.1

OTHER TIPS

mapply answer:

xmat <- matrix(c(0,1,1,1,1,0,0,0,1,1,0,1),nrow=4)
mapply(function(x,y) y[as.character(x)], data.frame(xmat),ruletable)

   X1  X2  X3
0 0.2 0.6 0.1
1 0.5 0.5 0.1
1 0.5 0.5 0.8
1 0.5 0.5 0.1

If you don't want the names, they are easy to remove:

unname(mapply(function(x,y) y[as.character(x)], data.frame(xmat),ruletable))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top