R提供最大值和最小值,但除了对整个矢量进行排序而不是从此向量中选取值x之外,我没有看到在序列中找到另一个值的快速方法。
是否有更快的方法来获得第二高的值(例如)?
由于
答案 0 :(得分:184)
使用partial
的{{1}}参数。第二个最高值:
sort()
答案 1 :(得分:48)
稍微慢一点,只为记录:
x <- c(12.45,34,4,0,-234,45.6,4)
max( x[x!=max(x)] )
min( x[x!=min(x)] )
答案 2 :(得分:27)
我将Rob的答案包含在稍微更通用的功能中,可用于查找第2,第3,第4(等)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)
答案 3 :(得分:15)
这是一种查找向量中N个最小值/最大值的索引的简单方法(N = 3的示例):
N <- 3
N最小:
ndx <- order(x)[1:N]
N最大:
ndx <- order(x, decreasing = T)[1:N]
因此您可以将值提取为:
x[ndx]
答案 4 :(得分:11)
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
使用10个百万号码:
N = 1e6
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
答案 5 :(得分:5)
对于第n个最高值,
sort(x, TRUE)[n]
答案 6 :(得分:3)
我发现首先删除max元素,然后以相当的速度执行另一次最大运行:
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
答案 7 :(得分:3)
这是我发现的最简单的方法,
num <- c(5665,1615,5154,65564,69895646)
num <- sort(num, decreasing = F)
tail(num, 1) # Highest number
head(tail(num, 2),1) # Second Highest number
head(tail(num, 3),1) # Third Highest number
head(tail(num, n),1) # Generl equation for finding nth Highest number
答案 8 :(得分:2)
给你... kit是明显的赢家!
N = 1e6
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]],
kit = x[kit::topn(x, 5L,decreasing = T)[5L]]
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# Rfast 12.311168 12.473771 16.36982 12.702134 16.110779 102.749873 100
# maxN 12.922118 13.124358 17.49628 18.977537 20.053139 28.928694 100
# order 50.443100 50.926975 52.54067 51.270163 52.323116 66.561606 100
# kit 1.177202 1.216371 1.29542 1.240228 1.297286 2.771715 100
编辑:我忘了 kit::topn
有 hasna
选项...让我们再运行一次。
microbenchmark::microbenchmark(
Rfast = Rfast::nth(x,5,descending = T),
maxN = maxN(x,5),
order = x[order(x, decreasing = T)[5]],
kit = x[kit::topn(x, 5L,decreasing = T)[5L]],
kit2 = x[kit::topn(x, 5L,decreasing = T,hasna = F)[5L]],
unit = "ms"
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# Rfast 13.194314 13.358787 14.7227116 13.4560340 14.551194 24.524105 100
# maxN 7.378960 7.527661 10.0747803 7.7119715 12.217756 67.409526 100
# order 50.088927 50.488832 52.4714347 50.7415680 52.267003 70.062662 100
# kit 1.180698 1.217237 1.2975441 1.2429790 1.278243 3.263202 100
# kit2 0.842354 0.876329 0.9398055 0.9109095 0.944407 2.135903 100
答案 9 :(得分:1)
当我最近寻找 R 函数返回给定向量中最高N max / min数的索引时,我很惊讶没有这样的函数。
这是非常相似的。
使用 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]
}
然后你可以从上面的函数defiend的结果中选择最后一个( N )项。
注意:上面定义的函数只是示例 - 如果要使用它们,则必须检查/完整性输入(例如 N&gt; length(x))。
我在http://palusga.cz/?p=18写了一篇关于非常类似的东西的小文章(得到矢量的前N个最大值/最小值的索引) - 你可以在这里找到我上面定义的类似函数的一些基准。
答案 10 :(得分:1)
head(sort(x),..)
或tail(sort(x),...)
应该有效
答案 11 :(得分:0)
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个值及其索引的矩阵。 希望能帮助到你 VDevi-周
答案 12 :(得分:0)
这将找到输入数值向量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)
}
答案 13 :(得分:0)
dplyr具有函数nth,其中第一个参数是向量,第二个参数是您想要的位置。这也适用于重复元素。 例如:
x = c(1,2, 8, 16, 17, 20, 1, 20)
找到第二大值:
nth(unique(x),length(unique(x))-1)
[1] 17
答案 14 :(得分:-1)
您可以使用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()
,您必须调整丢失的第一个元素。向量v
的完整代码为:
which(sign(diff(cummax(v)))==1)+1
答案 15 :(得分:-2)
您可以使用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个最大数字。