Відповіді:
Скористайтеся partial
аргументом sort()
. Для другого найвищого значення:
n <- length(x)
sort(x,partial=n-1)[n-1]
sort(x, TRUE)[2]
описаного у відповіді @ Абрара, окрім того, що він не задовольняє обмеженню у питанні?
Error in sort.int(x, na.last = na.last, decreasing = decreasing, ...) : index 4705 outside bounds
Будь-яке уявлення про те, що може бути проблемою? Деякі деталі: My x - числовий вектор довжиною 4706 з деякими NA
s в даних. Я намагався отримати друге найвище значення у векторі, використовуючи той самий код, що і @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)])
Я переклав відповідь Роба на трохи більш загальну функцію, яку можна використовувати для пошуку 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)
Поверне 5-й за величиною елемент x, в той час
Rfast::nth(x, 5, descending = F)
Повернеться 5-й найменший елемент x
Нижче наведено орієнтири проти найбільш популярних відповідей.
Для 10 тис. Номерів:
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]
Я виявив, що спочатку витягніть максимальний елемент, а потім виконайте ще один макс-біг із порівнянною швидкістю:
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
Ось найпростіший спосіб, який я знайшов,
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
Коли я нещодавно шукав функцію R, що повертає індекси верхніх N max / min чисел у заданому векторі, я був здивований, що такої функції немає.
І це щось дуже схоже.
Рішення з грубою силою за допомогою функції base :: order здається найпростішим.
topMaxUsingFullSort <- function(x, N) {
sort(x, decreasing = TRUE)[1:min(N, length(x))]
}
Але це не найшвидший випадок, якщо ваше N значення порівняно невелике порівняно з довжиною вектора x .
З іншого боку, якщо N дійсно малий, ви можете використовувати base :: thatMax ітеративно функціонувати, і в кожній ітерації ви можете замінити знайдене значення на -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 є використання часткової бази :: сортування .
topMaxUsingPartialSort <- function(x, N) {
N <- min(N, length(x))
x[x >= -sort(-x, partial=N)[N]][1:N]
}
Тоді ви можете вибрати останній ( N- й) елемент з результатів функцій, що захищаються вище.
Примітка: функції, визначені вище, - лише приклади - якщо ви хочете їх використовувати, ви повинні перевірити / вводити дані (наприклад, N> довжина (x) ).
Я написав невелику статтю про щось дуже схоже (отримати індекси верхніх N max / min значень вектора) на http://palusga.cz/?p=18 - ви можете знайти тут деякі орієнтири подібних функцій, які я визначив вище.
head(sort(x),..)
або tail(sort(x),...)
повинні працювати
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
Це знайде індекс N-го найменшого або найбільшого значення у вхідному числовому векторі x. Встановіть низ = ІСТИНА в аргументах, якщо ви хочете N'th знизу, або знизу = FALSE, якщо ви хочете N'th зверху. N = 1 і низ = TRUE еквівалентно, який.min, N = 1 і нижній = FALSE еквівалентний, який.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 має функцію nth, де перший аргумент - вектор, а другий - яке місце ви хочете. Це стосується і повторюваних елементів. Наприклад:
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
Ви можете використовувати таке 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 максимальних чисел.
topn
функцію , яка швидшеsort
,order
іnth
. Подивіться на документацію.