Menu

Ordenação no R: sort(), order() e arrange()

Como a ordenação realmente funciona no R: sort() para vetores, por que data frames precisam do truque de índices do order(), ordenações decrescentes e por múltiplas colunas, e o arrange() do dplyr.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

sort() Ordena os Valores de um Vetor

Para um vetor simples, sort() faz exatamente o que você espera - retorna os valores em ordem crescente (o original fica intocado):

Duas opções que vale a pena conhecer. decreasing = TRUE inverte a direção. E sort() silenciosamente descarta valores NA por padrão - sort(c(3, NA, 1)) retorna apenas 1 3. Se os valores ausentes precisam sobreviver à ordenação, diga onde eles vão: sort(x, na.last = TRUE) os mantém, colocados depois dos valores ordenados.

Até aqui, nada de novo. A parte interessante é por que sort() é a ferramenta errada para data frames.

order() Retorna Posições - A Mudança Mental

sort() responde "quais são os valores, em ordem?" order() responde a uma pergunta diferente: "quais posições eu visitaria para ver os valores em ordem?"

Leia order(times) como instruções: o menor valor está na posição 2, o próximo na posição 4, depois 1, depois 3. Indexar com essas instruções - times[order(times)] - reproduz sort(times) exatamente.

Por que isso importa? Porque uma linha de data frame é um time de valores que precisa se mover junto. Ordenar a coluna time sozinha com sort() reordenaria uma coluna e deixaria suas companheiras para trás - todas as linhas embaralhadas. order() fornece as posições das linhas, e colocar posições no espaço das linhas dos colchetes move linhas inteiras:

O 9.8 do Ben chega com o nome do Ben ainda anexado. Esse é todo o truque, e é o idioma para ordenar data frames no R base: df[order(df$column), ]. (Os rótulos de linha impressos - 2 4 1 3 - são os números originais das linhas acompanhando; inofensivo.)

Ordenações Decrescentes e por Múltiplas Colunas

Para ordenações numéricas decrescentes, negue a coluna - ordenar -time de forma crescente é ordenar time de forma decrescente. E order() aceita múltiplas colunas, as primeiras têm prioridade, as seguintes desempatam:

A segunda chamada ordena os departamentos alfabeticamente e, dentro de cada departamento, os salários do maior para o menor. O truque da negação só funciona com números - -df$name em uma coluna de texto é um erro. Para texto decrescente, use order(df$name, decreasing = TRUE) (que inverte todas as chaves de ordenação de uma vez).

rank() É o Terceiro Irmão

De passagem: rank(x) responde a mais uma pergunta - "que colocação cada valor ocupa?" - sem mover nada:

sort() fornece os valores ordenados, order() fornece as posições a visitar, rank() fornece a colocação de cada valor no lugar. As pessoas confundem order() e rank() o tempo todo; note que eles são permutações inversas um do outro, e recorra a rank() apenas quando você quer literalmente classificações (rankings, percentis).

O Jeito dplyr: arrange()

O arrange() do dplyr embrulha toda a dança do order() em um verbo - as colunas são chaves de ordenação e desc() inverte uma delas (estático; o sandbox executa apenas R base):

library(dplyr)

runners |> arrange(time)
staff   |> arrange(dept, desc(salary))

Sem colchetes, sem $, sem truque de negação - desc() funciona também com colunas de texto. Uma diferença de comportamento que vale conhecer: arrange() coloca os valores NA no final independentemente da direção, enquanto o order() do R base também tem na.last = TRUE como padrão. Veja a introdução ao dplyr para saber como arrange() se encadeia com filter() e companhia.

Ordenar Texto Tem Arestas Afiadas

Duas ressalvas ao ordenar texto. Primeira: dígitos armazenados como texto são ordenados como texto - a comparação de caracteres vai símbolo por símbolo:

"10" vem antes de "2" porque a comparação para no primeiro símbolo: "1" < "2". Se uma coluna de números ordena de forma estranha, quase certamente ela está armazenada como texto - converta com as.numeric() primeiro (uma consequência frequente de uma importação de CSV bagunçada).

Segunda: a ordenação de texto depende do locale do seu sistema - acentos, maiúsculas/minúsculas e alfabetos não latinos podem ordenar de forma diferente no seu notebook e em um servidor com locale C. Uma saída ordenada que precisa ser idêntica entre máquinas deve definir o locale explicitamente ou ordenar uma chave normalizada.

O Que Você Leva Daqui

  • sort(x) ordena os valores de um vetor; decreasing = TRUE inverte; NAs são descartados a menos que use na.last = TRUE.
  • order(x) retorna posições, e df[order(df$x), ] é o idioma do R base para ordenar data frames.
  • Múltiplas colunas: order(df$a, -df$b); a negação para ordem decrescente funciona apenas com números.
  • rank() fornece colocações sem reordenar - não é um substituto para order().
  • O arrange(dept, desc(salary)) do dplyr é a mesma ordenação com menos pontuação.
  • "10" vem antes de "2" em texto - confira os tipos das suas colunas.

A seguir: colapsar linhas em resumos por grupo com table(), tapply(), aggregate() e o group_by() do dplyr.

Perguntas frequentes

Como ordeno um data frame por uma coluna no R?

Use order() dentro dos colchetes na posição das linhas: df[order(df$price), ]. order() retorna as posições das linhas em ordem, e indexar com elas reorganiza o data frame inteiro. sort() não serve aqui - ele ordena os valores de um único vetor, perdendo a conexão deles com as outras colunas.

Qual é a diferença entre sort() e order() no R?

sort(x) retorna os valores de x reorganizados em ordem. order(x) retorna as posições (índices) que colocariam x em ordem - que é o que você precisa para ordenar um data frame inteiro por uma de suas colunas: df[order(df$x), ].

Como ordeno em ordem decrescente no R?

Para um vetor: sort(x, decreasing = TRUE). Para um data frame: df[order(-df$x), ] (negue uma coluna numérica) ou df[order(df$x, decreasing = TRUE), ], que também funciona para colunas de texto, onde a negação não funciona. No dplyr: arrange(df, desc(x)).

Como ordeno por múltiplas colunas no R?

Passe todas para order(): df[order(df$dept, -df$salary), ] ordena por departamento e, dentro de cada departamento, por salário em ordem decrescente. Os primeiros argumentos são as chaves primárias; os seguintes desempatam. No dplyr: arrange(df, dept, desc(salary)).

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR