回答:
のpartial
引数を使用しますsort()
。2番目に高い値の場合:
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はNA
、データにいくつかのs を含む長さ4706の数値ベクトルです。@RobHyndmanが提案したのとまったく同じコードを使用して、ベクトルの2番目に高い値を取得しようとしました。
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)])
私はロブの答えをもう少し一般的な関数にまとめました。これを使用して、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)
maxN(1:10, 1:3)
(デフォルトのNを1に設定しました)
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
1つのための百万の数字:
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番目に高い値の場合、
sort(x, TRUE)[n]
最近、特定のベクトルで上位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値のインデックスを取得)を書きました-ここで、上で定義した類似の関数のいくつかのベンチマークを見つけることができます。
head(sort(x),..)
または動作するtail(sort(x),...)
はずです
これは、入力数値ベクトル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があり、最初の引数はベクトルで、2番目は必要な場所です。これは繰り返し要素にも当てはまります。例えば:
x = c(1,2, 8, 16, 17, 20, 1, 20)
2番目に大きい値を見つける:
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倍遅いようです。300 length(x)
万です。
次に高い値をで識別できます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
topn
より高速な関数をsort
、order
とnth
。ドキュメントを見てください。