How to convert values in a matrix based on a list of rules without using for-loop in R

StackOverflow https://stackoverflow.com/questions/21769988

  •  11-10-2022
  •  | 
  •  

Pregunta

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!

¿Fue útil?

Solución

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

Otros consejos

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))
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top