Rはmaxとminを提供しますが、ベクトル全体を並べ替える以外に、このベクトルから値xを選択する以外の順序で別の値を見つけるための本当に速い方法は見当たりません。
2番目に高い値(たとえば)を取得するより速い方法はありますか?
ありがとう
sort()
のpartial
引数を使用します。 2番目に高い値の場合:
n <- length(x)
sort(x,partial=n-1)[n-1]
記録のためだけに、少し遅い選択肢:
x <- c(12.45,34,4,0,-234,45.6,4)
max( x[x!=max(x)] )
min( x[x!=min(x)] )
Robの答えを少し一般的な関数にまとめ、2番目、3番目、4番目(など)の最大値を見つけるために使用できます。
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)
ベクトル内のN個の最小/最大値のインデックスを見つける簡単な方法を次に示します(N = 3の例):
N <- 3
N最小:
ndx <- order(x)[1:N]
N最大:
ndx <- order(x, decreasing = T)[1:N]
したがって、値を次のように抽出できます。
x[ndx]
Rfastには、nth_elementという関数があります。この関数は、要求されたとおりに機能し、上記のすべての実装よりも高速です。
また、部分ソートに基づいた上記のメソッドは、k 最小値の検索をサポートしていません
Rfast::nth(x, 5, descending = T)
Xの5番目に大きい要素を返しますが、
Rfast::nth(x, 5, descending = F)
Xの5番目に小さい要素を返します
最も人気のある回答に対する以下のベンチマーク。
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
N番目に高い値の場合、
sort(x, TRUE)[n]
最初にmax要素を削除してから、同等の速度で別の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
最近、特定のベクトルの上位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値が大きくなると急速に遅くなります。そして、あなたはベクトルのすべての要素を繰り返していますxN回。
CleanRの最良の解決策は、部分base :: sort。
topMaxUsingPartialSort <- function(x, N) {
N <- min(N, length(x))
x[x >= -sort(-x, partial=N)[N]][1:N]
}
次に、上記の関数の結果から最後の(Nth)項目を選択できます。
注:上記で定義した関数は単なる例です-使用したい場合は、入力をチェック/サニティする必要があります(例:N> length(x) )。
http://palusga.cz/?p=18 で、非常によく似たもの(ベクトルの上位N最大/最小値のインデックスを取得)に関する小さな記事を書きました-ここにいくつかのベンチマークがあります上記で定義した同様の関数の。
head(sort(x),..)
またはtail(sort(x),...)
は動作するはずです
dplyrには関数nthがあり、最初の引数はベクトルで、2番目の引数は目的の場所です。これは繰り返し要素にも当てはまります。例えば:
x = c(1,2, 8, 16, 17, 20, 1, 20)
2番目に大きい値を見つける:
nth(unique(x),length(unique(x))-1)
[1] 17
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-Chouに役立つことを願って
これにより、入力数値ベクトル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)
}