Given a binary matrix, I want to generate a list of the positions of the 1s by row. For example:
> M <- matrix(c(1,1,0,0,1,1,1,0,1), 3, 3)
> M
[,1] [,2] [,3]
[1,] 1 0 1
[2,] 1 1 0
[3,] 0 1 1
> apply(M==1, 1, which, simplify = FALSE)
[[1]]
[1] 1 3
[[2]]
[1] 1 2
[[3]]
[1] 2 3
However, in versions of R before 4.1.0, the apply()
function automatically simplifies, which means the result will sometimes not be a list, but gets simplified into a vector or matrix. For example:
> apply(M==1, 1, which)
[,1] [,2] [,3]
[1,] 1 1 2
[2,] 3 2 3
How can I ensure the output will always be a list, even in earlier versions of R when the simplify = F
parameter isn't available for apply()
? Thanks!
CodePudding user response:
You can use asplit
, which splits the matrix into a list of vectors by the selected margin. Then use lapply
on the result to apply the which
to each vector.
lapply(asplit(M == 1, 1), which)
#> [[1]]
#> [1] 1 3
#>
#> [[2]]
#> [1] 1 2
#>
#> [[3]]
#> [1] 2 3
CodePudding user response:
We may use which
with arr.ind = TRUE
and then split
by the 'row'
ind <- which(M == 1, arr.ind = TRUE)
split(ind[,2], ind[, 1])
$`1`
[1] 1 3
$`2`
[1] 1 2
$`3`
[1] 2 3