Answers:
使用的partial
参数sort()
。对于第二高的值:
n <- length(x)
sort(x,partial=n-1)[n-1]
sort(x, TRUE)[2]
除了不满足问题中的约束条件之外,与@Abrar的答案中所述的方法相比,该方法的优点是什么?
Error in sort.int(x, na.last = na.last, decreasing = decreasing, ...) : index 4705 outside bounds
任何想法可能是什么问题?一些细节:My x是长度为4706的数字矢量,NA
数据中带有s。我尝试使用与@RobHyndman建议的完全相同的代码来获取向量中的第二个最大值。
decreasing
参数与部分排序不兼容,但您始终可以-sort(-x, partial=n-1)[n-1]
;从逻辑上讲,这是同一件事,而且比sort(x, decreasing=TRUE)[n-1]
。
替代方法稍微慢一些,仅用于记录:
x <- c(12.45,34,4,0,-234,45.6,4)
max( x[x!=max(x)] )
min( x[x!=min(x)] )
max(x[-which.max(x)])
Rfast具有一个称为nth_element的函数,它可以完全满足您的要求,并且比上述所有实现都要快
也在上面所讨论的方法是基于局部排序,不支持找到k个最小的值
Rfast::nth(x, 5, descending = T)
将返回x的第五大元素,而
Rfast::nth(x, 5, descending = F)
将返回x的第五个最小元素
以下是针对最流行答案的基准。
对于1万个数字:
N = 10000
x = rnorm(N)
maxN <- function(x, N=2){
len <- length(x)
if(N>len){
warning('N greater than length(x). Setting N=length(x)')
N <- length(x)
}
sort(x,partial=len-N+1)[len-N+1]
}
microbenchmark::microbenchmark(
Rfast = Rfast::nth(x,5,descending = T),
maxn = maxN(x,5),
order = x[order(x, decreasing = T)[5]]
)
Unit: microseconds
expr min lq mean median uq max neval
Rfast 160.364 179.607 202.8024 194.575 210.1830 351.517 100
maxN 396.419 423.360 559.2707 446.452 487.0775 4949.452 100
order 1288.466 1343.417 1746.7627 1433.221 1500.7865 13768.148 100
对于一百万个数字:
N = 1e6 #evaluates to 1 million
x = rnorm(N)
microbenchmark::microbenchmark(
Rfast = Rfast::nth(x,5,descending = T),
maxN = maxN(x,5),
order = x[order(x, decreasing = T)[5]]
)
Unit: milliseconds
expr min lq mean median uq max neval
Rfast 89.7722 93.63674 114.9893 104.6325 120.5767 204.8839 100
maxN 150.2822 207.03922 235.3037 241.7604 259.7476 336.7051 100
order 930.8924 968.54785 1005.5487 991.7995 1031.0290 1164.9129 100
Rfast::nth
可以返回多个元素(例如,第8个和第9个最大的元素)以及这些元素的索引。
这是查找向量中N个最小/最大值的索引的简单方法(例如N = 3):
N <- 3
N最小:
ndx <- order(x)[1:N]
N最大:
ndx <- order(x, decreasing = T)[1:N]
因此,您可以将值提取为:
x[ndx]
当我最近寻找给定向量中前N个最大/最小编号的索引的R函数时,令我惊讶的是,没有这样的函数。
这是非常相似的东西。
使用base :: order函数的强力解决方案似乎是最简单的解决方案。
topMaxUsingFullSort <- function(x, N) {
sort(x, decreasing = TRUE)[1:min(N, length(x))]
}
但是,如果您的N值与向量x的长度相比相对较小,则它不是最快的方法。
另一方面,如果N很小,则可以迭代使用base :: whichMax函数,并且在每次迭代中,都可以用-Inf替换找到的值
# the input vector 'x' must not contain -Inf value
topMaxUsingWhichMax <- function(x, N) {
vals <- c()
for(i in 1:min(N, length(x))) {
idx <- which.max(x)
vals <- c(vals, x[idx]) # copy-on-modify (this is not an issue because idxs is relative small vector)
x[idx] <- -Inf # copy-on-modify (this is the issue because data vector could be huge)
}
vals
}
我相信您已经看到了问题-R的修改后复制性质。因此,对于非常非常小的N(1,2,3),它会表现更好,但对于较大的N值,它将迅速放慢速度。您正在遍历向量x N次中的所有元素。
我认为干净的R中最好的解决方案是使用局部base :: sort。
topMaxUsingPartialSort <- function(x, N) {
N <- min(N, length(x))
x[x >= -sort(-x, partial=N)[N]][1:N]
}
然后您可以从上面定义的函数结果中选择最后一个(第N个)项目。
注意:上面定义的功能仅是示例-如果要使用它们,则必须检查/理清输入(例如N> length(x))。
我在http://palusga.cz/?p=18上写了一篇关于非常相似的东西的小文章(获取向量的前N个max / min值的索引)-在这里您可以找到一些我上面定义的相似函数的基准。
这将在输入数值向量x中找到第N个最小值或最大值的索引。如果要从底部开始第N个,请在参数中设置bottom = TRUE,如果要从顶部开始第N个,请在bottom = FALSE中设置。N = 1和bottom = TRUE等效于which.min,N = 1和bottom = FALSE等效于which.max。
FindIndicesBottomTopN <- function(x=c(4,-2,5,-77,99),N=1,bottom=FALSE)
{
k1 <- rank(x)
if(bottom==TRUE){
Nindex <- which(k1==N)
Nindex <- Nindex[1]
}
if(bottom==FALSE){
Nindex <- which(k1==(length(x)+1-N))
Nindex <- Nindex[1]
}
return(Nindex)
}
dplyr具有函数nth,其中第一个参数是向量,第二个参数是您想要的位置。这也适用于重复元素。例如:
x = c(1,2, 8, 16, 17, 20, 1, 20)
寻找第二大价值:
nth(unique(x),length(unique(x))-1)
[1] 17
x[[order(order_by)[[n]]]]
-因此需要对整个向量进行排序。因此,它不会像接受的答案那样快。
sort
与partial =参数一起使用(这会改变一切)
dplyr::nth()
?bench::mark(max(x[-which.max(x)]), x[[order(-x)[[2]]]] )
,nth()
几乎慢了10倍,即length(x)
300万。
您可以使用确定下一个更高的值cummax()
。例如,如果您想要每个新的较高值的位置,则可以将cummax()
值向量传递给diff()
函数以标识cummax()
值更改的位置。说我们有载体
v <- c(4,6,3,2,-5,6,8,12,16)
cummax(v) will give us the vector
4 6 6 6 6 6 8 12 16
现在,如果您想查找更改的位置,则cummax()
可以使用许多选项sign(diff(cummax(v)))
。由于,您必须调整丢失的第一个元素diff()
。vector的完整代码为v
:
which(sign(diff(cummax(v)))==1)+1
您可以sort
像这样使用关键字:
sort(unique(c))[1:N]
例:
c <- c(4,2,44,2,1,45,34,2,4,22,244)
sort(unique(c), decreasing = TRUE)[1:5]
将给出前5个最大数字。
topn
功能比更快sort
,order
和nth
。查看文档。