r语言 - 查找条件语句的最小值,其中条件也满足之后的所有值



我想确定第一个小于 1 的值,并且此元素后面的所有值也小于 1 且小于或等于该值。

我有一个DT:

stack <- data.table(a = as.numeric(seq(1,10,1)),
b = as.numeric(c(1.54, 1.17, 0.75, 1.65, 0.61, 0.31, 0.90, 0.07, 0.04, 0.01)),
ID = as.numeric(rep(seq(1,2,1),5)))
stack
a    b ID
1:  1 1.54  1
2:  2 1.17  2
3:  3 0.75  1
4:  4 1.65  2
5:  5 0.61  1
6:  6 0.31  2
7:  7 0.90  1
8:  8 0.07  2
9:  9 0.04  1
10: 10 0.01  2

我在此示例中查找的值将是第 7 行:

a    b ID
7: 7 0.90  1

这是第一个小于 1 的值,其中后面的所有值都小于 1,并且也小于或等于该值。我对从第a列返回值特别感兴趣。

我已经尝试过stack[,min(which(b < 1))]但这显然缺少额外的条件要求

另一种方法:

library(data.table)
set.seed(0L)
M <- 1e4
DT <- data.table(a=1:M, b=10*runif(M))
mtd1 <- function() {
DT[which(b < 1 &
sapply(seq_len(.N), 
function(i) all(b[min(.N, i + 1):nrow(DT)] <= b[i]))
)[1]]   
}
mtd2 <- function() {
DT[order(-b), .SD[b < 1][1L]]
}
identical(mtd1(), mtd2())
#[1] TRUE
library(microbenchmark)
microbenchmark(mtd1(), mtd2(), times=3L)

计时:

Unit: milliseconds
expr      min       lq       mean   median        uq      max neval
mtd1() 737.5113 754.3420 766.047900 771.1728 780.31620 789.4596     3
mtd2()   1.6830   1.7687   3.118033   1.8544   3.83555   5.8167     3
stack[which(b < 1 &
sapply(seq_len(.N), 
function(i) all(b[min(.N, i + 1):nrow(stack)] <= b[i]))
)[1]]

如果b[i] < 1b[i + x] <= b[i]我们不需要检查是否b[i + x] < 1

或者通过ID

fun <- function(b){
N <- length(b)
which(b < 1 &
sapply(seq_len(N), 
function(i) all(b[min(N, i + 1):N] <= b[i]))
)[1] == seq_len(N)
}
setorder(stack, ID)
stack[stack[, fun(b), by = ID]$V1]

编辑:

我无法删除这篇文章,因为它已被接受,但我意识到这在许多情况下给出了不正确的答案,例如下面的答案。另一个答案是正确的(无论如何要快得多(。

set.seed(0)
DT <- data.table(a=1:10, b=1.1*runif(10))

最新更新