Given a 0/1 matrix, I am trying to generate a list of the index positions of the 1s in each row. I can do this using a for loop:
B <- matrix(sample(c(0,1),100,replace=T),nrow=10,ncol=10)
ones <- list()
for (row in 1:nrow(B)) {ones[[row]] <- (which(B[row,]==1))}
The resulting object ones is what I want. I assume using apply() will be slightly faster, but I'm having trouble translating the loop into apply. This doesn't yield the same result:
alt <- apply(B, 1, function(x) which(B[x,]==1))
I'd appreciate any advice on how to correct apply so it yields the same result as the loop approach. Thanks!
UPDATE -
I accepted @TarJae’s answer because it works, only requires one line, and is fast. @Ronak’s approach also works, but is slower than either of the other options. Here’s a comparison of the three methods:
library(rbenchmark)
B <- matrix(sample(c(0,1),1000000,replace=T),nrow=1000,ncol=1000)
benchmark(
"loop" = {
ones_loop <- list()
for (row in 1:nrow(B)) {ones_loop[[row]] <- (which(B[row,]==1))}
},
"apply" = {
ones_apply <- apply(B==1,1, which)
},
"split" = {
ones_split <- which(B == 1, arr.ind = TRUE)
ones_split <- split(ones_split[, 2], ones_split[, 1])
},
replications = 500
)
test replications elapsed relative user.self sys.self user.child sys.child
2 apply 500 17.211 1.000 15.068 2.111 0 0
1 loop 500 19.466 1.131 16.778 2.349 0 0
3 split 500 40.291 2.341 33.757 6.150 0 0