Respuestas:
Usa el partial
argumento de sort()
. Para el segundo valor más alto:
n <- length(x)
sort(x,partial=n-1)[n-1]
sort(x, TRUE)[2]
lo descrito en la respuesta de @ Abrar, además de no satisfacer la restricción en la pregunta?
Error in sort.int(x, na.last = na.last, decreasing = decreasing, ...) : index 4705 outside bounds
Alguna idea de cuál podría ser el problema? Algunos detalles: Mi x es un vector numérico de longitud 4706 con algunos NA
s en los datos. Intenté obtener el segundo valor más alto en el vector usando exactamente el mismo código que sugirió @RobHyndman.
decreasing
argumento no es compatible con la ordenación parcial, siempre puedes -sort(-x, partial=n-1)[n-1]
; lógicamente es lo mismo y lleva mucho menos tiempo que sort(x, decreasing=TRUE)[n-1]
.
Alternativa ligeramente más lenta, solo para los registros:
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)])
Envolví la respuesta de Rob en una función un poco más general, que se puede usar para encontrar el segundo, tercero, cuarto (etc.) máximo:
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)
(hubiera configurado el valor predeterminado N a 1)
Rfast tiene una función llamada nth_element que hace exactamente lo que le pides y es más rápida que todas las implementaciones discutidas anteriormente
Además, los métodos discutidos anteriormente que se basan en una ordenación parcial, no admiten encontrar los k valores más pequeños
Rfast::nth(x, 5, descending = T)
Devolverá el quinto elemento más grande de x, mientras que
Rfast::nth(x, 5, descending = F)
Devolverá el quinto elemento más pequeño de x
Los puntos de referencia a continuación contra las respuestas más populares.
Por 10 mil números:
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
Para 1 millón de números:
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
puede devolver múltiples elementos (por ejemplo, el octavo y el noveno elemento más grande), así como los índices de esos elementos.
Aquí hay una manera fácil de encontrar los índices de N valores más pequeños / más grandes en un vector (Ejemplo para N = 3):
N <- 3
N más pequeño:
ndx <- order(x)[1:N]
N más grande:
ndx <- order(x, decreasing = T)[1:N]
Para que pueda extraer los valores como:
x[ndx]
Para el enésimo valor más alto,
sort(x, TRUE)[n]
Descubrí que eliminar el elemento max primero y luego hacer otra carrera máxima a una velocidad comparable:
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
Aquí está la forma más simple que encontré,
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
Cuando estaba buscando recientemente una función R que devolviera índices de los N números máximos / mínimos superiores en un vector dado, me sorprendió que no existiera dicha función.
Y esto es algo muy similar.
La solución de fuerza bruta usando la función base :: order parece ser la más fácil.
topMaxUsingFullSort <- function(x, N) {
sort(x, decreasing = TRUE)[1:min(N, length(x))]
}
Pero no es el más rápido en caso de que su valor de N sea relativamente pequeño en comparación con la longitud del vector x .
Por otro lado, si la N es realmente pequeña, puede usar la función base :: whichMax de forma iterativa y en cada iteración puede reemplazar el valor encontrado por -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
}
Creo que usted ve el problema: la naturaleza de copiar y modificar de R. Por lo tanto, funcionará mejor para N muy muy pequeño (1,2,3) pero se ralentizará rápidamente para valores de N más grandes. Y está iterando sobre todos los elementos en vector x N veces.
Creo que la mejor solución en clean R es usar parcial base :: sort .
topMaxUsingPartialSort <- function(x, N) {
N <- min(N, length(x))
x[x >= -sort(-x, partial=N)[N]][1:N]
}
Luego puede seleccionar el último ( N º) elemento del resultado de las funciones definidas anteriormente.
Nota: las funciones definidas anteriormente son solo ejemplos: si desea usarlas, debe verificar / controlar las entradas (por ejemplo, N> longitud (x) ).
Escribí un pequeño artículo sobre algo muy similar (obtenga índices de los valores máximos de N máximos / mínimos de un vector) en http://palusga.cz/?p=18 ; aquí puede encontrar algunos puntos de referencia de funciones similares que definí anteriormente.
head(sort(x),..)
o tail(sort(x),...)
debería funcionar
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)
}
Esta función devolverá una matriz con los valores superiores de n y sus índices. espero que ayude a VDevi-Chou
Esto encontrará el índice del enésimo valor más pequeño o más grande en el vector numérico de entrada x. Establezca bottom = TRUE en los argumentos si desea el N'th desde abajo, o bottom = FALSE si desea el N'th desde arriba. N = 1 y bottom = TRUE es equivalente a which.min, N = 1 y bottom = FALSE es equivalente a 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 tiene la función nth, donde el primer argumento es el vector y el segundo es el lugar que desea. Esto también se aplica a elementos repetitivos. Por ejemplo:
x = c(1,2, 8, 16, 17, 20, 1, 20)
Encontrar el segundo valor más grande:
nth(unique(x),length(unique(x))-1)
[1] 17
x[[order(order_by)[[n]]]]
, por lo que requiere ordenar todo el vector. Por lo tanto, no será tan rápido como la respuesta aceptada.
sort
con el argumento parcial = (que lo cambia todo)
dplyr::nth()
? bench::mark(max(x[-which.max(x)]), x[[order(-x)[[2]]]] )
, nth()
parece casi 10 veces más lento, donde length(x)
son 3 millones.
Puede identificar el siguiente valor más alto con cummax()
. Si desea la ubicación de cada nuevo valor superior, por ejemplo, puede pasar su vector de cummax()
valores a la diff()
función para identificar las ubicaciones en las que cummax()
cambió el valor. decimos que tenemos el vector
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
Ahora, si desea encontrar la ubicación de un cambio cummax()
, tiene muchas opciones que suelo usar sign(diff(cummax(v)))
. Tienes que ajustar por el primer elemento perdido debido a diff()
. El código completo para el vector v
sería:
which(sign(diff(cummax(v)))==1)+1
Puede usar la sort
palabra clave de esta manera:
sort(unique(c))[1:N]
Ejemplo:
c <- c(4,2,44,2,1,45,34,2,4,22,244)
sort(unique(c), decreasing = TRUE)[1:5]
dará los primeros 5 números máximos.
topn
función que es más rápida quesort
,order
ynth
. Mira la documentación.