在R中有效地提取逻辑矩阵中每行的第一个TRUE

时间:2016-09-09 11:51:29

标签: r matrix

给出以下矩阵:

         A     B    C
[1,]  TRUE FALSE TRUE
[2,] FALSE  TRUE TRUE
[3,] FALSE FALSE TRUE
[4,] FALSE  TRUE TRUE
[5,] FALSE  TRUE TRUE
[6,]  TRUE  TRUE TRUE

m <- structure(c(TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, 
FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE), .Dim = c(6L, 
3L), .Dimnames = list(NULL, c("A", "B", "C")))

我们如何能够提取第一列,每行的TRUE值有效?当然,我们可以每行使用apply,然后获取min(which(...))

这是所需的输出:

[1] A B C B B A

This thread似乎与我的问题重复,但不是:

  1. 这里我们讨论的是逻辑矩阵非数字数据框
  2. 这里我们试图获得第一个TRUE的位置而不是最高值

4 个答案:

答案 0 :(得分:8)

我们可以使用max.col

colnames(m)[max.col(m, "first")]
#[1] "A" "B" "C" "B" "B" "A"

如果连续没有TRUE,那么我们可以将其更改为NA(如果需要)

colnames(m)[max.col(m, "first")*NA^!rowSums(m)]

ifelse

colnames(m)[ifelse(rowSums(m)==0, NA, max.col(m, "first"))]

答案 1 :(得分:7)

另一个愿景,使用which来处理矩阵的logical类:

colnames(m)[aggregate(col~row, data=which(m, arr.ind = TRUE), FUN=min)$col]
#[1] "A" "B" "C" "B" "B" "A"

我们得到TRUE值的索引,然后按行找到它们出现的最小(索引)列。

<强>基准

library(microbenchmark)
n <- matrix(FALSE, nrow=1000, ncol=500) # couldn't afford a bigger one...
n <- t(apply(n, 1, function(rg) {rg[sample(1:500, 1, replace=TRUE)] <- TRUE ; rg}))
colnames(n) <- paste0("name", 1:500)
akrun <- function(n){colnames(n)[max.col(n, "first")]}
cath <- function(n){colnames(n)[aggregate(col~row, data=which(n, arr.ind = TRUE), FUN=min)$col]}

all(akrun(n)==cath(n))
#[1] TRUE

microbenchmark(akrun(n), cath(n))
# expr       min        lq      mean    median        uq      max neval cld
#akrun(n)  6.985716  7.233116  8.231404  7.525513  8.842927 31.23469   100  a 
# cath(n) 18.416079 18.811473 19.586298 19.272398 20.262169 22.42786   100   b

答案 2 :(得分:4)

这是我的尝试。它不是一个单行,但它很快。

joe <-  function(x) {
    y <- which(x)
    nR <- nrow(x)
    myR <- y %% nR
    myR[myR==0] <- nR
    myNames <- colnames(x)[ceiling(y/nR)]
    myCols <- which(!(duplicated(myR)))
    myNames[myCols][order(myR[myCols])]
}

以下是使用@Cath提供的数据的基准:

microbenchmark(akrun(n), cath(n), joe(n))
Unit: microseconds
    expr       min        lq      mean    median        uq       max neval
akrun(n)  4248.760  5588.8640  6148.1816  5926.7130  6378.887 12502.437   100
 cath(n) 12641.189 13733.1415 14808.6524 14532.8115 15559.287 20628.037   100
  joe(n)   555.418   642.2405   758.5293   713.2585   800.697  4849.334   100

all.equal(akrun(n), cath(n), joe(n))
[1] TRUE

答案 3 :(得分:2)

这是另一种具有更好性能的方式w.r.t. @Cath解决方案:

A 0.0001 , B 0.0002 , C 0.0003

根据@Cath使用的矩阵进行基准测试:

a <- which(m, arr.ind = T)
colnames(m)[aggregate(col~row,a[order(a[,1]),],min)$col]

# [1] "A" "B" "C" "B" "B" "A"

因此,以下是排名解决方案(就效率而言):

  1. akrun
  2. m0h3n
  3. 蛋白酶