Reputation: 15085
Assume we have the following logical matrix in R:
A <- matrix(as.logical(c(0,0,0,1,0,1,0,0,1,0,0,0)), nrow=4)
# [,1] [,2] [,3]
# [1,] FALSE FALSE TRUE
# [2,] FALSE TRUE FALSE
# [3,] FALSE FALSE FALSE
# [4,] TRUE FALSE FALSE
I want to convert this matrix into a column-wise index using
B <- column_wise_index(A)
where column_wise_index
returns a vector containing the same number of elements as the number of rows in A
(4), and each element contains the column of A
that has a logical value TRUE
. For A
above, B
should resemble
B <- c(3,2,0,1)
# [1] 3 2 0 1
where 0
indicates a row that has no TRUE
value.
The closest I've come is apply
ing which
by row:
unlist(apply(A, 1, function(x) which(x)))
# [1] 3 2 1
However, the result skips 0
, and I'm not sure how efficient this is for large matrices (say ~100K x 100 entries).
Upvotes: 0
Views: 175
Reputation: 37661
Here is a solution that is more in the spirit of how you started, but you have to admire @rawr's clever solution.
A <- matrix(as.logical(c(0,0,0,1,0,1,0,0,1,0,0,0)), nrow=4)
TrueSpots = apply(A, 1, which)
TrueSpots[!sapply(TrueSpots, length)] = 0
unlist(TrueSpots)
[1] 3 2 0 1
Update including @akrun's suggestion:
TrueSpots = apply(A, 1, which)
TrueSpots[!lengths(TrueSpots)] = 0
unlist(TrueSpots)
[1] 3 2 0 1
Upvotes: 2
Reputation: 15085
max.col(A)
identifies the index where the maximum entry occurs within the row. Ties are broken at random (by default). rowSums(A)
on a logical matrix performs a per-row binary addition.
Based on the assumption that each row has at most one TRUE
value, rowSums(A)
will result in a binary vector. Performing a vector-based multiplication nullifies the truly FALSE
rows in A.
> A <- matrix(as.logical(c(0,0,0,1,0,1,0,0,1,0,0,0)), nrow=4)
> max.col(A)*rowSums(A)
[1] 3 2 0 1
Upvotes: 1