Yanıtlar:
Rfast , nth_element adlı, tam olarak sorduğunuz şeyi yapan ve yukarıda tartışılan tüm uygulamalardan daha hızlı bir işleve sahiptir.
Ayrıca yukarıda tartışılan ve kısmi sıralamaya dayanan yöntemler, en küçük değerlerin bulunmasını desteklemez
Rfast::nth(x, 5, descending = T)
X'in en büyük 5. öğesini döndürür
Rfast::nth(x, 5, descending = F)
X'in en küçük 5. öğesini döndürür
En popüler cevaplara karşı aşağıdaki karşılaştırmalar.
10 bin numara için:
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 milyon numara için:
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
Birden fazla elemanın (örneğin 8. ve 9. en büyük elemanlar) yanı sıra bu elemanların endekslerini döndürebileceğinden bahsetmektedir .
İfadesinin partial
argümanını kullanın sort()
. İkinci en yüksek değer için:
n <- length(x)
sort(x,partial=n-1)[n-1]
sort(x, TRUE)[2]
, sorudaki kısıtlamayı tatmin etmemek dışında, @ Abrar'ın cevabında tarif edilenin avantajı nedir ?
Error in sort.int(x, na.last = na.last, decreasing = decreasing, ...) : index 4705 outside bounds
Sorun ne olabilir? Bazı detaylar: Benim x, 4706 uzunluğunda sayısal bir vektördür ve bazı NA
veriler de s'dir. @RobHyndman önerilen tam olarak aynı kodu kullanarak vektör ikinci en yüksek değeri almaya çalıştım.
decreasing
argüman kısmi sıralama ile uyumlu olmasa da , her zaman -sort(-x, partial=n-1)[n-1]
; mantıksal olarak aynı şeydir ve olduğundan çok daha az zaman alır sort(x, decreasing=TRUE)[n-1]
.
Sadece kayıtlar için biraz daha yavaş bir alternatif:
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'un cevabını 2., 3., 4. (vb.) Maks. Bulmak için kullanılabilecek biraz daha genel bir işleve sardım:
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)
(varsayılan N değerini 1 olarak ayarlayabilirdim)
Bir vektördeki N en küçük / en büyük değerlerin indekslerini bulmanın kolay bir yolu (N = 3 örneği):
N <- 3
N En Küçük:
ndx <- order(x)[1:N]
En Büyük:
ndx <- order(x, decreasing = T)[1:N]
Böylece değerleri şöyle ayıklayabilirsiniz:
x[ndx]
En yüksek nci değer için,
sort(x, TRUE)[n]
Önce max elemanını kaldırmanın ve daha sonra karşılaştırılabilir hızda başka bir max çalıştırması yaptım:
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
İşte bulduğum en basit yol,
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
Son zamanlarda belirli bir vektörde üst N max / dak sayılarının indekslerini döndüren bir R işlevi ararken , böyle bir işlev olmadığına şaşırdım.
Ve bu çok benzer bir şey.
Base :: order fonksiyonunu kullanan kaba kuvvet çözümü en kolay çözüm gibi görünmektedir.
topMaxUsingFullSort <- function(x, N) {
sort(x, decreasing = TRUE)[1:min(N, length(x))]
}
Ancak N değerinizin x vektörünün uzunluğuna kıyasla nispeten küçük olması durumunda en hızlı olanı değildir .
Diğer tarafta N gerçekten küçükse, base :: whichMax işlevini yinelemeli olarak kullanabilirsiniz ve her yinelemede bulunan değeri -Inf ile değiştirebilirsiniz.
# 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
}
Sorunu gördüğünüze inanıyorum - R'nin kopyala-değiştir doğası Bu, çok çok çok küçük N (1,2,3) için daha iyi performans gösterecek, ancak daha büyük N değerleri için hızla yavaşlayacaktır. Ve vektör tüm elemanları yinelemek olan x N defa.
Ben temiz R en iyi çözüm kısmi base :: sort kullanmak olduğunu düşünüyorum .
topMaxUsingPartialSort <- function(x, N) {
N <- min(N, length(x))
x[x >= -sort(-x, partial=N)[N]][1:N]
}
Ardından, yukarıdaki fonksiyon fonksiyonlarının sonucundan son ( N. ) Öğeyi seçebilirsiniz.
Not: yukarıda tanımlanan fonksiyonlar sadece örnektir - bunları kullanmak istiyorsanız, girişleri kontrol etmelisiniz (örn. N> uzunluk (x) ).
Http://palusga.cz/?p=18 adresinde çok benzer bir şey hakkında küçük bir makale yazdım (bir vektörün üst N max / min değerlerinin dizinlerini alın) - burada yukarıda tanımladığım benzer işlevlerin bazı kriterlerini bulabilirsiniz.
head(sort(x),..)
ya da tail(sort(x),...)
çalışmalı
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)
}
bu işlev en üst n değerlerine ve indekslerine sahip bir matris döndürür. umarım VDevi-Chou'ya yardımcı olur
Bu, x giriş sayısal vektöründeki N'inci en küçük veya en büyük değerin dizinini bulur. En alttan N'th istiyorsanız bağımsız değişkenlerde bottom = TRUE, N'th'i üstten isterseniz bottom = FALSE olarak ayarlayın. N = 1 ve alt = DOĞRU olan ile eşdeğerdir. Min, N = 1 ve alt = YANLIŞ olan ile eşdeğerdir. Maks.
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, ilk argümanın vektör ve ikincisi istediğiniz yer olduğu nth işlevine sahiptir. Bu, elemanları tekrarlamak için de geçerlidir. Örneğin:
x = c(1,2, 8, 16, 17, 20, 1, 20)
İkinci en büyük değeri bulmak:
nth(unique(x),length(unique(x))-1)
[1] 17
x[[order(order_by)[[n]]]]
- bu yüzden tüm vektörü sıralamayı gerektirir. Bu yüzden kabul edilen cevap kadar hızlı olmayacak.
sort
kısmi = argümanla (her şeyi değiştirir) kullanır
dplyr::nth()
mi? bench::mark(max(x[-which.max(x)]), x[[order(-x)[[2]]]] )
, nth()
yaklaşık 10 kat daha yavaş görünüyor, nerede length(x)
3 milyon.
Bir sonraki daha yüksek değeri ile tanımlayabilirsiniz cummax()
. Örneğin, her yeni daha yüksek değerin konumunu istiyorsanız , değerin değiştiği konumları belirlemek için cummax()
değerler vektörünüzü diff()
işleve iletebilirsiniz cummax()
. vektörümüz olduğunu söyle
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
Şimdi, eğer bir değişikliğin yerini bulmak istiyorsanız, kullanmak istediğim cummax()
birçok seçeneğiniz var sign(diff(cummax(v)))
. Kayıp ilk eleman için ayar yapmanız gerekir diff()
. Vektör için tam kod v
:
which(sign(diff(cummax(v)))==1)+1
sort
Anahtar kelimeyi şu şekilde kullanabilirsiniz :
sort(unique(c))[1:N]
Misal:
c <- c(4,2,44,2,1,45,34,2,4,22,244)
sort(unique(c), decreasing = TRUE)[1:5]
ilk 5 maksimum sayıyı verecektir.
topn
daha hızlı olduğu işlevisort
,order
venth
. Belgelere bakın.