找出向量中小于阈值的最后一个元素的下标
假设我有一个向量,v:
v<-c(1,3,5,8,8,5,6,8,9,10)
其中的数值大致在增大,但并非完全均匀地增大。
我想要返回小于阈值的最后一个值的索引,在这个例子中阈值为 < 8。因此期望的输出应为7(也就是值为6 的那个元素的索引)。
将数据按小于8 进行子集提取并统计得到的向量长度并不能解决问题,因为在我们要找的值之前,可能已经出现了大于等于阈值的值。
我曾考虑用从向量末端向前搜索的for循环并返回第一个小于8 的值的索引,但这似乎是一种过于复杂的解法。
解决方案
获取满足条件的元素的索引,并取最后一个:
# 1
tail(which(v < 8), 1)
## [1] 7
上述方法在没有满足条件的元素时会返回一个长度为0 的结果。若要指定不同的结果,请使用这个(这里我们指定了NA,但它可以替换为任意期望的值,例如0):
# 2
(v < 0) |>
which() |>
tail(1) |>
c(NA) |>
head(1)
## [1] NA
或这个也可以很容易地做成一个接收逻辑向量和默认值的短函数:
# 3
(v < 0) |>
which() |>
(\(x) if (length(x)) tail(x, 1) else NA)()
## [1] NA
这个在没有匹配时返回NA:
# 4
rev(which(v < 0))[1]
## [1] NA
这个在没有匹配时返回0。它的效率比前面的实现低,但如果 v 的规模不大,或许也无所谓:
# 5
Reduce(max, init = 0, which(v < 0))
## [1] 0
性能
library(bench)
library(dplyr)
library(ggplot2)
v = c(1,3,5,8,8,5,6,8,9,10)
L <- list(v10 = v, v100 = sample(v, 100, TRUE), v1000 = sample(v, 1000, TRUE))
results <- press(
i = 1:3,
k = c(0, 8),
{ v = L[[i]]
mark(min_iterations = 100,
tail1 = c(tail(which(v < k), 1), NA)[[1]],
tail2 = (v < k) |> which() |> tail(1) |> c(NA) |> head(1),
tail3 = (v < k) |> which() |> (\(x) if (length(x)) tail(x, 1) else NA_integer_)(),
rev = rev(which(v < k))[1],
Reduce = Reduce(max, init = 0, which(v < k)) |> na_if(0L),
Position = Position(\(x) x < k, v, right=TRUE)
)
}
)
autoplot(results)
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。
