在vector或列中find第二个(第三…)最高/最低值的最快方法

R提供了最大值和最小值,但是除了sorting整个向量和从这个向量中select值x之外,我没有看到一个非常快速的方法来查找另一个值。

有更快的方法来获得第二高的价值(例如)?

谢谢

使用sort()partial参数。 对于第二高的值:

 n <- length(x) sort(x,partial=n-1)[n-1] 

稍微慢一点的select,只是为了logging:

 x <- c(12.45,34,4,0,-234,45.6,4) max( x[x!=max(x)] ) min( x[x!=min(x)] ) 

我把Rob的答案包装成一个稍微更一般的函数,可以用来查找第二,第三,第四(等)max:

 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] } maxN(1:10) 

这是一个简单的方法来find一个向量中N个最小/最大值的索引(N = 3的例子):

 N <- 3 

N最小:

 ndx <- order(x)[1:N] 

N最大:

 ndx <- order(x, decreasing = T)[1:N] 

所以你可以提取的值为:

 x[ndx] 

对于第n个最高值,

 sort(x, TRUE)[n] 

我发现,先删除最大的元素,然后做另一个最大运行速度相当:

 system.time({a=runif(1000000);m=max(a);i=which.max(a);b=a[-i];max(b)}) user system elapsed 0.092 0.000 0.659 system.time({a=runif(1000000);n=length(a);sort(a,partial=n-1)[n-1]}) user system elapsed 0.096 0.000 0.653 

当我最近正在寻找一个R函数返回给定向量中的最大N最大/最小值的索引时,我很惊讶没有这样的函数。

这是非常相似的东西。

使用base :: order函数的蛮力解决scheme似乎是最简单的。

 topMaxUsingFullSort <- function(x, N) { sort(x, decreasing = TRUE)[1:min(N, length(x))] } 

但是,如果N值与向量x的长度相比相对较小,那么它不是最快的。

另一方面,如果N非常小,则可以迭代地使用base :: whichMax函数,并且在每次迭代中,可以用-Inf来代替find的值

 # 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)来说会performance的更好,但是对于更大的N值,它会快速减慢。 而且你正在向量遍历所有元素N次。

我认为在干净的R最好的解决scheme是使用部分base :: sort

 topMaxUsingPartialSort <- function(x, N) { N <- min(N, length(x)) x[x >= -sort(-x, partial=N)[N]][1:N] } 

然后你可以从上面定义的函数的结果中select最后一个(第N个)项目。

注意:上面定义的函数只是一个例子 – 如果你想使用它们,你必须检查/健全性input(例如N> length(x) )。

我在http://palusga.cz/?p=18上写了一篇关于非常相似的东西的小文章(得到一个向量的最大N /最小值的索引) – 你可以在这里find一些我在上面定义的类似函数的基准。

head(sort(x),..)tail(sort(x),...)应该工作

 topn = function(vector, n){ maxs=c() ind=c() for (i in 1:n){ biggest=match(max(vector), vector) ind[i]=biggest maxs[i]=max(vector) vector=vector[-biggest] } mat=cbind(maxs, ind) return(mat) } 

这个函数将会返回一个包含前n个值和它们的索引的matrix。 希望它能帮助VDevi-Chou

这将在input数字向量x中find第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) } 

你可以通过cummax()来确定下一个更高的值。 例如,如果您想要每个新的更高值的位置,则可以将cummax()值的向量传递给diff()函数以确定cummax()值更改的位置。 说我们有vector

 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()find变化的位置,你有很多select,我倾向于使用sign(diff(cummax(v))) 。 你必须调整丢失的第一个元素,因为diff() 。 向量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个最大数字。