web-dev-qa-db-ja.com

ベクトルまたは列の2番目(3番目...)の最高/最低値を見つける最も速い方法

Rはmaxとminを提供しますが、ベクトル全体を並べ替える以外に、このベクトルから値xを選択する以外の順序で別の値を見つけるための本当に速い方法は見当たりません。

2番目に高い値(たとえば)を取得するより速い方法はありますか?

ありがとう

148
jorgusch

sort()partial引数を使用します。 2番目に高い値の場合:

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

記録のためだけに、少し遅い選択肢:

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

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)
27
Zach

ベクトル内のN個の最小/最大値のインデックスを見つける簡単な方法を次に示します(N = 3の例):

N <- 3

N最小:

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

N最大:

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

したがって、値を次のように抽出できます。

x[ndx]
15
Davit Sargsyan

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
11
Stefanos

N番目に高い値の場合、

sort(x, TRUE)[n]
5
Abrar

最初に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 
3
John Jiang

最近、特定のベクトルの上位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最大/最小値のインデックスを取得)に関する小さな記事を書きました-ここにいくつかのベンチマークがあります上記で定義した同様の関数の。

1
Donarus

head(sort(x),..)またはtail(sort(x),...)は動作するはずです

1
Job Mangelmans

dplyrには関数nthがあり、最初の引数はベクトルで、2番目の引数は目的の場所です。これは繰り返し要素にも当てはまります。例えば:

x = c(1,2, 8, 16, 17, 20, 1, 20)

2番目に大きい値を見つける:

 nth(unique(x),length(unique(x))-1)

[1] 17
0
Noale
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に役立つことを願って

0
vdc320

これにより、入力数値ベクトル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)
}
0
Ralph