\$\begingroup\$
\$\endgroup\$
4
I have a matrix A
containing numeric values and a matrix B
containing 0/1s:
A <- matrix(1:25, 5, 5)
B <- matrix(c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0), 5, 5)
A B
1 6 11 16 21 0 0 1 0 0
2 7 12 17 22 0 0 0 0 1
3 8 13 18 23 0 0 0 0 1
4 9 14 19 24 0 0 1 0 0
5 10 15 20 25 0 0 1 0 0
I want to extract the elements of A
where B==1
in row order. The desired result is:
11 22 23 14 15
I've come up with two possible ways to do this:
#1
rowSums(A*B)
#2
t(A)[as.logical(t(B))]
It seems like there should be a better (more elegant or faster) way to do this...
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
2 Answers 2
\$\begingroup\$
\$\endgroup\$
While rowSums(A*B)
looks pretty nice for me, you can also try
A[which(t(B) == 1, arr.ind = T)[,2:1]]
\$\begingroup\$
\$\endgroup\$
Although I don't have any substantial improvements, this is another way:
t(A)[t(B) == 1]
answered Aug 3, 2023 at 14:38
lang-r
t(A)
andt(B)
instead of asA
andB
so thatA[B]
will work. \$\endgroup\$B
matrix by a vector of indices, hereb = c(3, 5, 5, 3, 3)
. (I am basing my assumption that there is only one1
per row from yourrowSums(A*B)
suggestion). Storing the info in a vector is the most memory efficient. Then you could doA[cbind(seq_along(b), b)]
. Otherwise I findt(A)[as.logical(t(B))]
elegant enough and it is probably very fast. \$\endgroup\$