Werner
Werner

Reputation: 15085

Per-row index of a matrix in R (including 0-rows)

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

Answers (2)

G5W
G5W

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

Werner
Werner

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

Related Questions