我有data.table
行xe5
行和大约100列。我希望找到前3列索引,使其值不是NA
或0
。
m <- matrix(rep(NA_integer_, 1e6), ncol=10)
for(i in 1:nrow(m)){
set.seed(i);
m[i, sample(1:10, 5)] = 1L:5L
}
DT <- data.table(m);
DT
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1: NA 5 1 2 3 NA 4 NA NA NA
2: NA 1 NA NA 3 5 2 NA NA 4
3: NA 1 4 3 NA NA NA 2 5 NA
4: 2 4 3 NA 5 1 NA NA NA NA
5: 5 4 1 NA NA NA 2 3 NA NA
---
99996: NA NA 2 3 5 1 NA NA 4 NA
99997: 2 NA NA NA 1 NA NA 3 5 4
99998: 5 NA 4 2 NA 1 3 NA NA NA
99999: NA 5 NA 1 NA 4 NA 2 NA 3
100000: 5 NA NA NA 2 3 1 NA NA 4
f <- function(x){return(list(which(!is.na(x) & x!=0L)[1:3L]))}
#Here is what apply do
system.time(test <- apply(m, FUN=f, MAR=1))
utilisateur système écoulé
1.30 0.00 1.29
我发现它很慢,这可能不是data.table
的任务,我正在寻找一种快速的方法来获得这个答案(欢迎任何方法)。
答案 0 :(得分:4)
首先,您可以使用0 /0
为NaN
的事实,这也会为TRUE
提供is.na
。这将减少到一个!is.na
的条件。其次,您可以使用which
和arr.ind = TRUE
进行矢量化,即row
和col
索引。我们可以使用它来按row
拆分并获得前三个col
值,如下所示:
system.time(tt <- data.table(which(!is.na(DT[, lapply(.SD, function(x) x/0)]),
arr.ind=TRUE), key="row")[, col[1:3], by="row"])
user system elapsed
0.360 0.000 0.359
编辑:另一种方式:
DT <- DT[, lapply(.SD, function(x) !is.na(x/0))]
out <- data.table(matrix(numeric(3e5), ncol=3))
system.time({
for (i in as.integer(seq_along(DT))) {
for (j in 1:3) {
zeros <- .subset2(DT, i) & (out[[j]] == 0)
out[zeros, names(out)[j] := i]
DT[zeros, c(names(DT)[i]) := FALSE]
}
}
})
不确定它是否是最快的。