답변:
의 partial
인수를 사용하십시오 sort()
. 두 번째로 높은 값의 경우 :
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
문제가 무엇인지 알 수 있습니까? 일부 세부 사항 : 내 x는 길이가 4706 인 숫자 벡터로 NA
데이터에 일부 가 있습니다. @RobHyndman이 제안한 것과 동일한 코드를 사용하여 벡터에서 두 번째로 높은 값을 얻으려고했습니다.
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)])
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)
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의 다섯 번째로 작은 요소를 반환합니다
가장 인기있는 답변에 대한 아래의 벤치 마크.
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
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 에서 가장 좋은 해결책은 partial 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 최대 / 최소 값의 색인을 얻음)에 대한 작은 기사를 썼습니다. 여기서 위에서 정의한 유사한 함수의 벤치 마크를 찾을 수 있습니다.
입력 숫자 형 벡터 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에는 n 번째 함수가 있으며, 첫 번째 인수는 벡터이고 두 번째 인수는 원하는 위치입니다. 이것은 반복되는 요소에도 적용됩니다. 예를 들면 다음과 같습니다.
x = c(1,2, 8, 16, 17, 20, 1, 20)
두 번째로 큰 값 찾기 :
nth(unique(x),length(unique(x))-1)
[1] 17
x[[order(order_by)[[n]]]]
하므로 전체 벡터를 정렬해야합니다. 따라서 허용되는 답변만큼 빠르지는 않습니다.
sort
부분 = 인수 (모든 것을 변화하는)
dplyr::nth()
있습니까? bench::mark(max(x[-which.max(x)]), x[[order(-x)[[2]]]] )
, nth()
거의 10 배 더 느린 것 같습니다 length(x)
. 3 백만입니다.
로 다음으로 높은 값을 식별 할 수 있습니다 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
. 설명서를보십시오.