给出以下矩阵:
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似乎与我的问题重复,但不是:
答案 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"
因此,以下是排名解决方案(就效率而言):