[r] 벡터 또는 열에서 두 번째 (세 번째…) 최고 / 최저 값을 찾는 가장 빠른 방법

R은 최대 및 최소를 제공하지만 전체 벡터를 정렬 한 다음이 벡터에서 값 x를 선택하는 것과는 별도로 순서대로 다른 값을 찾는 빠른 방법은 없습니다.

예를 들어 두 번째로 높은 값을 얻는 더 빠른 방법이 있습니까?



답변

partial인수를 사용하십시오 sort(). 두 번째로 높은 값의 경우 :

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)


답변

Rfast 에는 nth_element 라는 함수가 있습니다.이 함수는 사용자가 요청한 것을 정확하게 수행하며 위에서 설명한 모든 구현보다 빠릅니다.

또한 부분 정렬을 기반으로 위에서 설명한 방법은 k 개의 가장 작은 값을 찾는 것을 지원하지 않습니다.

Rfast::nth(x, 5, descending = T)

x의 5 번째로 큰 요소를 반환합니다.

Rfast::nth(x, 5, descending = F)

x의 다섯 번째로 작은 요소를 반환합니다

가장 인기있는 답변에 대한 아래의 벤치 마크.

10,000 개의 숫자 :

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


답변

다음은 벡터에서 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]


답변

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