sort() ordena los valores de un vector
Para un vector normal, sort() hace exactamente lo que esperas: devuelve los valores en orden ascendente (el original queda intacto):
Dos opciones que conviene conocer. decreasing = TRUE invierte la dirección. Y sort() descarta silenciosamente los valores NA por defecto - sort(c(3, NA, 1)) devuelve solo 1 3. Si los valores faltantes deben sobrevivir a la ordenación, di dónde van: sort(x, na.last = TRUE) los conserva, colocados después de los valores ordenados.
Hasta aquí, todo obvio. Lo interesante es por qué sort() es la herramienta equivocada para los data frames.
order() devuelve posiciones - el cambio mental
sort() responde "¿cuáles son los valores, en orden?" order() responde a otra pregunta: "qué posiciones debería visitar para ver los valores en orden?"
Lee order(times) como instrucciones: el valor más pequeño está en la posición 2, el siguiente en la posición 4, luego la 1, luego la 3. Indexar con esas instrucciones - times[order(times)] - reproduce sort(times) exactamente.
¿Por qué importa eso? Porque una fila de un data frame es un equipo de valores que deben moverse juntos. Ordenar la columna time sola con sort() reordenaría una columna dejando atrás a sus compañeras - todas las filas revueltas. order() te da posiciones de fila en su lugar, y poner posiciones en el hueco de filas de los corchetes mueve filas completas:
El 9.8 de Ben llega con el nombre de Ben aún adjunto. Ese es todo el truco, y es el idioma para ordenar data frames en R base: df[order(df$column), ]. (Las etiquetas de fila impresas - 2 4 1 3 - son los números de fila originales que vienen de acompañantes; inofensivo.)
Órdenes descendentes y por varias columnas
Para órdenes numéricos descendentes, niega la columna - ordenar -time ascendente es ordenar time descendente. Y order() acepta varias columnas, las primeras primero, las siguientes deshaciendo empates:
La segunda llamada ordena los departamentos alfabéticamente y, dentro de cada departamento, los salarios de mayor a menor. El truco de la negación solo funciona con números - -df$name en una columna de caracteres es un error. Para texto descendente, usa order(df$name, decreasing = TRUE) en su lugar (que invierte todas las claves de ordenación a la vez).
rank() es el tercer hermano
De pasada: rank(x) responde a otra pregunta más - "¿qué puesto ocupa cada valor?" - sin mover nada:
sort() da los valores ordenados, order() da las posiciones a visitar, rank() da la posición de cada valor en su sitio. La gente confunde order() y rank() constantemente; fíjate en que son permutaciones inversas la una de la otra, y recurre a rank() solo cuando literalmente quieras rankings (tablas de clasificación, percentiles).
La forma dplyr: arrange()
El arrange() de dplyr envuelve todo el baile de order() en un verbo - las columnas son claves de ordenación, desc() invierte una (estático; el sandbox solo ejecuta R base):
library(dplyr)
runners |> arrange(time)
staff |> arrange(dept, desc(salary))
Sin corchetes, sin $, sin el truco de la negación - desc() funciona también con columnas de caracteres. Una diferencia de comportamiento que conviene conocer: arrange() coloca los valores NA al final independientemente de la dirección, mientras que el order() de base también tiene na.last = TRUE por defecto. Consulta la introducción a dplyr para ver cómo arrange() se encadena con filter() y compañía.
Ordenar caracteres tiene aristas afiladas
Dos advertencias al ordenar texto. Primera, los dígitos guardados como texto se ordenan como texto - la comparación de caracteres va símbolo a símbolo:
"10" se ordena antes que "2" porque la comparación se detiene en el primer símbolo: "1" < "2". Si una columna de números se ordena de forma rara, casi con seguridad está guardada como caracteres - conviértela primero con as.numeric() (una secuela frecuente de una importación de CSV desordenada).
Segunda, la ordenación de texto depende del locale de tu sistema - los acentos, las mayúsculas y las escrituras no latinas pueden ordenarse distinto en tu portátil que en un servidor con locale C. La salida ordenada que deba ser idéntica entre máquinas debería fijar el locale explícitamente u ordenar por una clave normalizada.
Lo que te llevas
sort(x)ordena los valores de un vector;decreasing = TRUElo invierte; losNAse descartan salvo conna.last = TRUE.order(x)devuelve posiciones, ydf[order(df$x), ]es el idioma de base para ordenar data frames.- Varias columnas:
order(df$a, -df$b); la negación para descendente solo funciona con números. rank()da puestos sin reordenar - no es un sustituto deorder().- El
arrange(dept, desc(salary))de dplyr es la misma ordenación con menos puntuación. "10"se ordena antes que"2"en texto - revisa los tipos de tus columnas.
A continuación: colapsar filas en resúmenes por grupo con table(), tapply(), aggregate() y el group_by() de dplyr.
Preguntas frecuentes
¿Cómo ordeno un data frame por una columna en R?
Usa order() dentro de los corchetes de filas: df[order(df$price), ]. order() devuelve las posiciones de las filas en orden, e indexar con ellas reordena el data frame completo. sort() no sirve aquí: ordena los valores de un solo vector, perdiendo su conexión con las demás columnas.
¿Cuál es la diferencia entre sort() y order() en R?
sort(x) devuelve los valores de x reordenados. order(x) devuelve las posiciones (índices) que pondrían x en orden - que es lo que necesitas para ordenar un data frame completo por una de sus columnas: df[order(df$x), ].
¿Cómo ordeno en orden descendente en R?
Para un vector: sort(x, decreasing = TRUE). Para un data frame: df[order(-df$x), ] (niega una columna numérica) o df[order(df$x, decreasing = TRUE), ], que también funciona con columnas de caracteres donde la negación no sirve. En dplyr: arrange(df, desc(x)).
¿Cómo ordeno por varias columnas en R?
Pásalas todas a order(): df[order(df$dept, -df$salary), ] ordena por departamento y luego por salario dentro de cada departamento, descendente. Los primeros argumentos son las claves primarias; los siguientes deshacen los empates. En dplyr: arrange(df, dept, desc(salary)).