Jawaban:
Rfast memiliki fungsi yang disebut nth_element yang melakukan persis apa yang Anda minta dan lebih cepat dari semua implementasi yang dibahas di atas
Juga metode yang dibahas di atas yang didasarkan pada semacam parsial, tidak mendukung menemukan k terkecil nilai-nilai
Rfast::nth(x, 5, descending = T)
Akan mengembalikan elemen x ke 5 terbesar, sementara
Rfast::nth(x, 5, descending = F)
Akan mengembalikan elemen terkecil ke-5 x
Tingkatan yang dicapai di bawah ini terhadap sebagian besar jawaban populer.
Untuk 10 ribu angka:
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
Untuk 1 juta angka:
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
dapat mengembalikan beberapa elemen (misalnya elemen terbesar ke-8 dan ke-9) serta indeks elemen-elemen tersebut.
Gunakan partial
argumen dari sort()
. Untuk nilai tertinggi kedua:
n <- length(x)
sort(x,partial=n-1)[n-1]
sort(x, TRUE)[2]
dijelaskan dalam jawaban @ Abrar, selain tidak memuaskan kendala dalam pertanyaan?
Error in sort.int(x, na.last = na.last, decreasing = decreasing, ...) : index 4705 outside bounds
Ada yang tahu apa masalahnya? Beberapa perincian: X saya adalah vektor numerik dengan panjang 4706 dengan beberapa NA
s dalam data. Saya mencoba untuk mendapatkan nilai tertinggi kedua dalam vektor menggunakan kode yang sama persis seperti yang disarankan oleh @RobHyndman.
decreasing
argumennya tidak kompatibel dengan penyortiran parsial, Anda selalu bisa -sort(-x, partial=n-1)[n-1]
; ini secara logis adalah hal yang sama dan membutuhkan waktu yang jauh lebih sedikit daripada sort(x, decreasing=TRUE)[n-1]
.
Alternatif sedikit lebih lambat, hanya untuk catatan:
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)])
Saya membungkus jawaban Rob menjadi fungsi yang sedikit lebih umum, yang dapat digunakan untuk menemukan maks 2, 3, 4 (dll):
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)
(saya akan mengatur default N ke 1)
Berikut adalah cara mudah untuk menemukan indeks N nilai terkecil / terbesar dalam vektor (Contoh untuk N = 3):
N <- 3
N Terkecil:
ndx <- order(x)[1:N]
N Terbesar:
ndx <- order(x, decreasing = T)[1:N]
Jadi, Anda dapat mengekstrak nilai sebagai:
x[ndx]
Untuk nilai tertinggi ke-n,
sort(x, TRUE)[n]
Saya menemukan bahwa menghapus elemen max terlebih dahulu dan kemudian menjalankan max lainnya dalam kecepatan yang sebanding:
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
Inilah cara paling sederhana yang saya temukan,
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
Ketika saya baru-baru ini mencari R fungsi mengembalikan indeks atas N max / angka min dalam vektor yang diberikan, saya terkejut tidak ada fungsi seperti itu.
Dan ini adalah sesuatu yang sangat mirip.
Solusi brute force menggunakan fungsi dasar :: order tampaknya yang paling mudah.
topMaxUsingFullSort <- function(x, N) {
sort(x, decreasing = TRUE)[1:min(N, length(x))]
}
Tetapi ini bukan yang tercepat jika nilai N Anda relatif kecil dibandingkan dengan panjang vektor x .
Di sisi lain jika N benar-benar kecil, Anda dapat menggunakan basis :: whichMax berfungsi secara iteratif dan di setiap iterasi Anda dapat mengganti nilai yang ditemukan dengan -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
}
Saya percaya Anda melihat masalah - sifat copy-on-memodifikasi R. Jadi ini akan bekerja lebih baik untuk N sangat sangat sangat kecil (1,2,3) tetapi akan cepat melambat untuk nilai N yang lebih besar. Dan Anda mengulangi semua elemen dalam vektor x N kali.
Saya pikir solusi terbaik dalam clean R adalah dengan menggunakan basis parsial :: sort .
topMaxUsingPartialSort <- function(x, N) {
N <- min(N, length(x))
x[x >= -sort(-x, partial=N)[N]][1:N]
}
Kemudian Anda dapat memilih yang terakhir ( N th) item dari hasil fungsi defiend di atas.
Catatan: fungsi yang didefinisikan di atas hanyalah contoh - jika Anda ingin menggunakannya, Anda harus memeriksa / input sanity (mis. N> panjang (x) ).
Saya menulis sebuah artikel kecil tentang sesuatu yang sangat mirip (dapatkan indeks nilai maksimal N / min maksimum vektor) di http://palusga.cz/?p=18 - Anda dapat menemukan di sini beberapa tolok ukur fungsi serupa yang saya tetapkan di atas.
head(sort(x),..)
atau tail(sort(x),...)
harus bekerja
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)
}
fungsi ini akan mengembalikan matriks dengan nilai n atas dan indeksnya. harap ini membantu VDevi-Chou
Ini akan menemukan indeks dari N'th nilai terkecil atau terbesar di input numerik vektor x. Setel bawah = BENAR dalam argumen jika Anda ingin N'th dari bawah, atau bawah = FALSE jika Anda ingin N'th dari atas. N = 1 dan bawah = BENAR setara dengan which.min, N = 1 dan bawah = FALSE setara dengan yang.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 memiliki fungsi n, di mana argumen pertama adalah vektor dan yang kedua adalah tempat yang Anda inginkan. Ini berlaku untuk elemen berulang juga. Sebagai contoh:
x = c(1,2, 8, 16, 17, 20, 1, 20)
Menemukan nilai terbesar kedua:
nth(unique(x),length(unique(x))-1)
[1] 17
x[[order(order_by)[[n]]]]
- jadi ini membutuhkan pengurutan seluruh vektor. Jadi itu tidak akan secepat jawaban yang diterima.
sort
dengan argumen parsial = (yang mengubah segalanya)
dplyr::nth()
? bench::mark(max(x[-which.max(x)]), x[[order(-x)[[2]]]] )
, nth()
sepertinya hampir 10 kali lebih lambat, di mana length(x)
3 juta.
Anda dapat mengidentifikasi nilai yang lebih tinggi berikutnya dengan cummax()
. Jika Anda ingin lokasi masing-masing nilai baru yang lebih tinggi misalnya, Anda dapat meneruskan vektor cummax()
nilai Anda ke diff()
fungsi untuk mengidentifikasi lokasi di mana cummax()
nilai berubah. katakanlah kita memiliki vektor
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
Sekarang, jika Anda ingin menemukan lokasi perubahan, cummax()
Anda memiliki banyak opsi yang cenderung saya gunakan sign(diff(cummax(v)))
. Anda harus menyesuaikan elemen pertama yang hilang karena diff()
. Kode lengkap untuk vektor v
adalah:
which(sign(diff(cummax(v)))==1)+1
Anda dapat menggunakan sort
kata kunci seperti ini:
sort(unique(c))[1:N]
Contoh:
c <- c(4,2,44,2,1,45,34,2,4,22,244)
sort(unique(c), decreasing = TRUE)[1:5]
akan memberikan 5 angka maks pertama.
topn
fungsi yang lebih cepat daripadasort
,order
dannth
. Lihatlah dokumentasinya.