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
  •  | 
  •  

Вопрос

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!

Это было полезно?

Решение

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

Другие советы

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))
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top