Reputation: 381
Given a binary matrix B
, I can usually get a list of the column indexes of the 1s by row using Blist <- apply(B==1, 1, which)
. However, this doesn't work when, for example, rowSums(B)[1] == rowSums(B)[2]
.
Here's an example where it works:
> B <- matrix(c(1,1,0,0,1,0,0,0,1),3,3)
> B
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 1 1 0
[3,] 0 0 1
> Blist <- apply(B==1, 1, which)
> Blist
[[1]]
[1] 1
[[2]]
[1] 1 2
[[3]]
[1] 3
Here's an example when it doesn't work:
> B <- matrix(c(1,0,0,0,1,0,0,0,1),3,3)
> B
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 1 0
[3,] 0 0 1
> Blist <- apply(B==1, 1, which)
> Blist
[1] 1 2 3
In this case, the desired result is:
> Blist
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
How can I modify Blist <- apply(B==1, 1, which)
so that the result is always organized as a list?
Upvotes: 4
Views: 167
Reputation: 32548
m = which(B == 1, arr.ind=TRUE)
split(m[,"col"], m[,"row"])
# $`1`
# [1] 1
# $`2`
# [1] 2
# $`3`
# [1] 3
Upvotes: 2
Reputation: 887501
There is simplify
argument which is TRUE
by default. The default usage from ?apply`
apply(X, MARGIN, FUN, ..., simplify = TRUE)
simplify - a logical indicating whether results should be simplified if possible.
Also, it states
If the calls to FUN return vectors of different lengths, or if simplify is FALSE, apply returns a list of length prod(dim(X)[MARGIN]) with dim set to MARGIN if this has length greater than one.
apply(B==1, 1, which, simplify = FALSE)
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
Upvotes: 3