# Extract numerics from matrix A with logical matrix B

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

• Did you profile both? – Mast Aug 27 '18 at 16:45
• @Mast -- Not yet. In my application, my matrices are fairly small, but they occur in a loop that is called many times. I just figured that this would be a fairly common matrix operation, but I couldn't find "direct" way to implement it. – DanY Aug 27 '18 at 16:49
• @Amstel made a point (that is now deleted), but maybe the "solution" is to store information as t(A) and t(B) instead of as A and B so that A[B] will work. – DanY Aug 27 '18 at 16:59
• If how you store your information is up for changes/review, I'd recommend you replace the B matrix by a vector of indices, here b = c(3, 5, 5, 3, 3). (I am basing my assumption that there is only one 1 per row from your rowSums(A*B) suggestion). Storing the info in a vector is the most memory efficient. Then you could do A[cbind(seq_along(b), b)]. Otherwise I find t(A)[as.logical(t(B))] elegant enough and it is probably very fast. – flodel Aug 28 '18 at 2:15

While rowSums(A*B) looks pretty nice for me, you can also try
A[which(t(B) == 1, arr.ind = T)[,2:1]]