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