La forma más rápida de encontrar el segundo (tercero …) valor más alto / más bajo en vector o columna

R ofrece max y min, pero no veo una forma realmente rápida de encontrar el otro valor en el orden aparte de ordenar todo el vector y de elegir el valor x de este vector.

¿Hay una forma más rápida de obtener el segundo valor más alto (por ejemplo)?

Gracias

Usa el argumento partial de sort() . Por el segundo valor más alto:

 n <- length(x) sort(x,partial=n-1)[n-1] 

Alternativa un poco 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)] ) 

Envolví la respuesta de Rob en una función ligeramente más general, que se puede usar para encontrar el 2 °, 3 °, 4 ° (etc.) máx .:

 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) 

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] 

Entonces puedes extraer los valores como:

 x[ndx] 

Por enésimo valor más alto,

 sort(x, TRUE)[n] 

Descubrí que eliminando primero el elemento máximo y luego hago otras carreras máximas 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 

Cuando hace poco estaba buscando una función R que devuelva índices de N máx. / Min superior en un vector determinado, me sorprendió que no exista tal función.

Y esto es algo muy similar.

La solución de fuerza bruta que usa 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 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 ve el problema, la naturaleza de copiar en la modificación de R. Entonces, esto funcionará mejor para N muy (muy) muy pequeño (1, 2, 3) pero se ralentizará rápidamente para valores de N más grandes. Y estás iterando sobre todos los elementos en vector x N veces.

Creo que la mejor solución en clean R es usar partial 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 ítem (Nth) del resultado de las funciones defiend arriba.

Nota: las funciones definidas anteriormente son solo ejemplos: si desea usarlas, debe verificar las entradas / cordura (por ejemplo, N> longitud (x) ).

Escribí un pequeño artículo sobre algo muy similar (obtener índices de los valores máximos N máx. / Mín. 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 n valores superiores y sus índices. Espero que ayude a VDevi-Chou

Esto encontrará el índice del N-é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 quiere la N’th desde abajo, o bottom = FALSE si quiere la N’th desde la parte superior. N = 1 e inferior = VERDADERO 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) } 

Puede identificar el siguiente valor más alto con cummax() . Si desea la ubicación de cada nuevo valor más alto, por ejemplo, puede pasar su vector de valores cummax() a la función diff() para identificar las ubicaciones en las que cambió el valor de cummax() . decir 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 quieres encontrar la ubicación de un cambio en cummax() tienes muchas opciones, sign(diff(cummax(v))) 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 palabra clave sort como esta:

 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.

dplyr tiene la función nth, donde el primer argumento es el vector y el segundo es el lugar que desea. Esto también sirve para repetir elementos. 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