在向量中查找第一个大于 X 的值的位置

Find position of first value greater than X in a vector

我有一个向量,想找到第一个大于 100 的值的位置。

# Randomly generate a suitable vector
set.seed(0)
v <- sample(50:150, size = 50, replace = TRUE)

min(which(v > 100))

假设值是你的向量。

 firstGreatearThan <- NULL
  for(i in seq(along=values)) { 
    if(values[i] > 100) {
       firstGreatearThan <- i
       break
    }
 }

查看 which.max

x <- seq(1, 150, 3)
which.max(x > 100)
# [1] 35
x[35]
# [1] 103

解决方法有很多,还有一个是:

x <- 90:110
which(x > 100)[1]

大多数基于 whichmax 的答案都很慢(尤其是对于长向量),因为它们遍历 整个 向量:

  1. x>100 评估向量中的每个 值,看它是否符合条件
  2. whichmax/min 搜索 所有 在第 1 步 return 编辑的索引,并找到 maximum/minimum

Position 只会评估条件,直到它遇到第一个 TRUE 值并立即 return 相应的索引,而不继续通过向量的其余部分。

# Randomly generate a suitable vector
v <- sample(50:150, size = 50, replace = TRUE)

Position(function(x) x > 100, v)

顺便提一下,Hadley Wickham 已经实现了一个函数 detect_index,以在他的 purrr 函数式编程包中完成这个任务。

我最近用过 detect_index 自己,会推荐给遇到同样问题的其他人。

可在此处找到 detect_index 的文档:https://rdrr.io/cran/purrr/man/detect.html

因为我需要在一个循环中多次执行类似的计算,所以我很想知道这个线程中提供的许多答案中哪一个最有效。

TLDR: 无论第一个值在向量中出现得早还是晚,which.max(v > 100) 是解决此问题的最快方法。

但是请注意,如果v中没有条目超过100,它将return 1;因此可能有理由

SafeWhichMax <- function (v) {
  first <- which.max(v > 100)
  if (first == 1L && v[1] <= 100) NA else first
}
SafeWhichMax(100) # NA
SafeWhichMax(101) # 1

如果向量很长并且不能保证包含任何 TRUE 结果,match(TRUE, v > 100) 可能比 which.max() 检查更快。

# Short vector:
v <- 0:105

microbenchmark(
  which.max(v > 100),
  match(TRUE, v > 100),
  min(which(v > 100)),
  which(v > 100)[1],
  Position(function(x) x, v > 100),
  Position(function(x) x > 100, v),
  purrr::detect_index(v, function (x) x > 100)
)
Unit: microseconds
                                  mean      median
which.max(v > 100)                24.112    23.80
SafeWhichMax(v)                   24.889    24.25
match(TRUE, v > 100)              34.752    33.20
min(which(v > 100))               25.506    25.20
which(v > 100)[1]                 25.320    24.90
Position(function(x) x, v > 100)  3231.783  3043.50
Position(function(x) x > 100, v)  3487.805  3314.75
purrr::detect_index               16436.579 16064.90
# Long vector, with late first occurrence of v > 100
v <- -10000:105
Unit: microseconds
                                  mean   median
which.max(v > 100)               24.958    24.30
SafeWhichMax(v)                  25.456    24.90
match(TRUE, v > 100)             37.680    37.85
min(which(v > 100))              26.439    26.00
which(v > 100)[1]                25.724    25.55
Position(function(x) x, v > 100) 3224.240  3036.50
Position(function(x) x > 100, v) 3389.538  3287.05
purrr::detect_index              17344.706 15283.35