1
\$\begingroup\$

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

\$\endgroup\$
  • \$\begingroup\$ Did you profile both? \$\endgroup\$ – Mast Aug 27 '18 at 16:45
  • \$\begingroup\$ @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. \$\endgroup\$ – Dan Y Aug 27 '18 at 16:49
  • \$\begingroup\$ @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. \$\endgroup\$ – Dan Y Aug 27 '18 at 16:59
  • 3
    \$\begingroup\$ 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. \$\endgroup\$ – flodel Aug 28 '18 at 2:15
0
\$\begingroup\$

While rowSums(A*B) looks pretty nice for me, you can also try

A[which(t(B) == 1, arr.ind = T)[,2:1]]
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.