벡터 또는 열에서 두 번째(세 번째...) 가장 높은/낮은 값을 찾는 가장 빠른 방법
R은 max와 min을 제공하지만 전체 벡터를 정렬한 다음 이 벡터에서 값 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)] )
Rfast에는 사용자가 요청한 대로 정확히 수행하는 nth_element라는 함수가 있습니다.
또한 부분 정렬에 기반한 위의 방법은 k개의 최소값 찾기를 지원하지 않습니다.
업데이트(28/2/21) 패키지 키트를 사용하면 구현 속도가 빨라집니다(상위 n). https://stackoverflow.com/a/66367996/4729755, 를 참조하십시오.
고지 사항:as.numeric(예: Rfast::nth(as.numeric(1:10), 2))을 사용하여 우회할 수 있는 정수를 처리할 때 문제가 발생하며 Rfast의 다음 업데이트에서 해결됩니다.
Rfast::nth(x, 5, descending = T)
x의 5번째로 큰 요소를 반환하는 동안
Rfast::nth(x, 5, descending = F)
x의 5번째 작은 원소를 반환합니다.
가장 일반적인 답변과 비교하여 아래의 벤치마크를 제공합니다.
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
100만 개의 숫자:
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
Rob의 답변을 두 번째, 세 번째, 네 번째(등) 최대값을 찾는 데 사용할 수 있는 약간 더 일반적인 함수로 요약했습니다.
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]
n번째로 높은 값의 경우
sort(x, TRUE)[n]
여기 있습니다...키트가 확실한 승자입니다!
N = 1e6
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]],
kit = x[kit::topn(x, 5L,decreasing = T)[5L]]
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# Rfast 12.311168 12.473771 16.36982 12.702134 16.110779 102.749873 100
# maxN 12.922118 13.124358 17.49628 18.977537 20.053139 28.928694 100
# order 50.443100 50.926975 52.54067 51.270163 52.323116 66.561606 100
# kit 1.177202 1.216371 1.29542 1.240228 1.297286 2.771715 100
편집: 깜빡했습니다.kit::topn
가지다hasna
한번 한 번 더 뛰죠.
microbenchmark::microbenchmark(
Rfast = Rfast::nth(x,5,descending = T),
maxN = maxN(x,5),
order = x[order(x, decreasing = T)[5]],
kit = x[kit::topn(x, 5L,decreasing = T)[5L]],
kit2 = x[kit::topn(x, 5L,decreasing = T,hasna = F)[5L]],
unit = "ms"
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# Rfast 13.194314 13.358787 14.7227116 13.4560340 14.551194 24.524105 100
# maxN 7.378960 7.527661 10.0747803 7.7119715 12.217756 67.409526 100
# order 50.088927 50.488832 52.4714347 50.7415680 52.267003 70.062662 100
# kit 1.180698 1.217237 1.2975441 1.2429790 1.278243 3.263202 100
# kit2 0.842354 0.876329 0.9398055 0.9109095 0.944407 2.135903 100
여기 제가 찾은 가장 간단한 방법이 있습니다.
num <- c(5665,1615,5154,65564,69895646)
num <- sort(num, decreasing = F)
tail(num, 1) # Highest number
head(tail(num, 2),1) # Second Highest number
head(tail(num, 3),1) # Third Highest number
head(tail(num, n),1) # Generl equation for finding nth Highest number
먼저 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
dplyr에는 n번째 함수가 있으며, 여기서 첫 번째 인수는 벡터이고 두 번째는 원하는 위치입니다.반복되는 요소도 마찬가지입니다.예:
x = c(1,2, 8, 16, 17, 20, 1, 20)
두 번째로 큰 값 찾기:
nth(unique(x),length(unique(x))-1)
[1] 17
최근 주어진 벡터에서 상위 N max/min 숫자의 인덱스를 반환하는 R 함수를 찾고 있을 때, 그런 함수가 없다는 것에 놀랐습니다.
그리고 이것은 매우 유사한 것입니다.
base:: order 기능을 이용한 브루트 포스 솔루션이 가장 쉬운 것 같습니다.
topMaxUsingFullSort <- function(x, N) {
sort(x, decreasing = TRUE)[1:min(N, length(x))]
}
그러나 N 값이 벡터 x의 길이에 비해 상대적으로 작은 경우에는 가장 빠른 값이 아닙니다.
N이 정말 작으면 base::max 함수를 반복적으로 사용할 수 있으며 각 반복에서 찾은 값을 -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에서 가장 좋은 해결책은 부분 베이스::sort를 사용하는 것이라고 생각합니다.
topMaxUsingPartialSort <- function(x, N) {
N <- min(N, length(x))
x[x >= -sort(-x, partial=N)[N]][1:N]
}
그런 다음 위에서 정의한 함수의 결과에서 마지막(N번째) 항목을 선택할 수 있습니다.
참고: 위에서 정의한 기능은 예제에 불과합니다. 사용하려면 입력을 확인/검사해야 합니다(예:길이(x).
저는 http://palusga.cz/ ?p=18에서 매우 유사한 것(벡터의 상위 N max/min 값의 인덱스 가져오기)에 대한 작은 기사를 썼습니다. 위에서 정의한 유사한 함수의 벤치마크를 여기에서 찾을 수 있습니다.
head(sort(x),..)
또는tail(sort(x),...)
효과가 있어야 합니다.
입력 숫자 벡터 x에서 N번째로 작거나 큰 값의 인덱스를 찾습니다. 아래쪽 =아래에서 N번째를 원하는 경우 인수에서 TRUE 또는 아래=처음부터 N'th를 원한다면 FALSE입니다.N=1 및 하단=TRUE는 다음과 같습니다.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)
}
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에 도움이 되길 바랍니다.
다음으로 높은 값을 식별할 수 있습니다.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
사용할 수 있습니다.sort
다음과 같은 키워드:
sort(unique(c))[1:N]
예:
c <- c(4,2,44,2,1,45,34,2,4,22,244)
sort(unique(c), decreasing = TRUE)[1:5]
처음 5개의 최대 숫자를 제공합니다.
언급URL : https://stackoverflow.com/questions/2453326/fastest-way-to-find-second-third-highest-lowest-value-in-vector-or-column
'IT' 카테고리의 다른 글
JDBC 연결에서 TNS 이름과 서비스 이름을 사용하는 것의 차이점 (0) | 2023.07.07 |
---|---|
Vuex에서 작업으로 개체 전달 문제 (0) | 2023.07.07 |
python 명령줄을 종료하는 중 (0) | 2023.07.07 |
Spring Boot 통합 시 @Schedule 사용 안 함시험 (0) | 2023.07.07 |
'WITH' 절을 사용하여 SQL Server 쿼리에 이상한 오류가 발생함 (0) | 2023.07.07 |