Classificar linhas em data.table em ordem decrescente na chave da string `order (-x, v)` gera erro no data.table 1.9.4 ou anterior

125

Digamos que eu tenho o seguinte data.tableem R:

  library(data.table)
  DT = data.table(x=rep(c("b","a","c"),each=3), y=c(1,3,6), v=1:9)

Quero ordená-lo por duas colunas (digamos colunas xe v). Eu usei isso:

 DT[order(x,v)] # sorts first by x then by v (both in ascending order)

Mas agora, quero classificá-lo por x(em ordem decrescente) e ter o seguinte código:

  DT[order(-x)] #Error in -x : invalid argument to unary operator

Portanto, acho que esse erro se deve ao fato de que class(DT$x)=character. Você poderia me dar alguma sugestão para resolver esse problema?

Sei que posso usar DT[order(x,decreasing=TRUE)], mas quero conhecer a sintaxe para classificar por várias colunas usando os dois modos (alguns diminuindo, outros aumentando) ao mesmo tempo.

Observe que se você usar DT[order(-y,v)]o resultado está ok, mas se você usar, DT[order(-x,v)]há um erro. Então, minha pergunta é: como resolver esse erro?

nhern121
fonte
6
Pergunta interessante, mas se você estiver trabalhando com grandes conjuntos de dados, provavelmente deverá definir chaves para suas tabelas de dados. As chaves colocam seus dados em uma ordem que maximiza a indexação subsequente, subconjunto, agregação por grupos etc. Esse pode não ser o seu formato preferido para imprimir os dados, mas geralmente é um preço pequeno a pagar pela velocidade que você obterá .
Josh O'Brien
No entanto, parece-me que DT[order(-x)]não é uma afirmação equivalente a, setorder(DT, -x)porque setorder()na verdade age DTenquanto o outro não. Declarações equivalentes seriam DT <- DT [ordem (-x)] setorder (DT, -x) Eu sou muito novo em R, então corrija se estiver enganado.
jeromeResearch
@jerome Você está correto. Pankil não disse que eles eram equivalentes, então eu acho que está tudo bem como está.
24417 Frank
1
Concordo com o @smci que uma edição de título faz sentido aqui, embora eu a altere para indicar que essa pergunta não é mais relevante, por exemplo, adicionando "no data.table 1.9.4 ou anterior" ao título para que as pessoas não o façam continue aqui do google esperando algo mais. Eu fiz isso com uma das minhas perguntas: stackoverflow.com/questions/30035939/… #
Frank
1
Nestorggh, não reverter o novo título, a menos que você possa melhorá-lo. "classificar linhas no data.table" não disse quase nada, que a funcionalidade básica estava lá para yonks. O título precisa mencionar seu problema real (várias chaves em que uma é decrescente). Também é importante que esse seja um problema conhecido no 1.9.4 e anterior e não seja mais um problema.
SMCI

Respostas:

144

Atualizar

O data.table v1.9.6 + agora suporta a tentativa original do OP e a resposta a seguir não é mais necessária.


Você pode usar DT[order(-rank(x), y)].

   x y v
1: c 1 7
2: c 3 8
3: c 6 9
4: b 1 1
5: b 3 2
6: b 6 3
7: a 1 4
8: a 3 5
9: a 6 6
Matthew Plourde
fonte
1
Conforme apontado por @PankilShah abaixo, isso foi corrigido por algum tempo e a abordagem original do OP agora funciona conforme o esperado. Não consegui encontrar o commit, pois ele foi corrigido no nível C e não sei o que procurar.
22416 MichaelChirico
1
Legal, obrigado. Parece improvável que alguém acabe aqui ... mas, por outro lado, eu mesmo acabei aqui pesquisando algo vagamente relacionado.
22416 MichaelChirico
@MichaelChirico, na verdade, recebo rotineiramente votos positivos para esta resposta, então estou muito feliz que você tenha apontado isso. Não sou realmente um usuário do data.table e não acompanho seu desenvolvimento.
Matthew Plourde 12/02
É muito útil para indicar o número da versão atual (1.9.6?), Por isso não tem que ir caçar em arquivos do NEWS.md .
SMCI
23

Você pode usar apenas -as entradas numéricas, para diminuir e negar as que deseja em ordem crescente:

DT[order(x,-v,decreasing=TRUE),]
      x y v
 [1,] c 1 7
 [2,] c 3 8
 [3,] c 6 9
 [4,] b 1 1
 [5,] b 3 2
 [6,] b 6 3
 [7,] a 1 4
 [8,] a 3 5
 [9,] a 6 6
James
fonte
3
Eu gosto dessa maneira, a menos que você tenha duas charactercolunas e queira classificar uma aumentando e a outra diminuindo.
Matthew Plourde
1
@plourde Acho que você pode combinar sua solução com esta para resolver o problema que você colocou. Por exemplo, você pode colocar: DT[order(x,-rank(w),decreasing=TRUE)]dado isso xe wsão as duas colunas de caracteres. Obrigado!
precisa saber é o seguinte
17

DT[order(-x)]funciona como esperado. Tenho data.table versão 1.9.4. Talvez isso tenha sido corrigido em uma versão recente.
Além disso, sugiro a setorder(DT, -x)sintaxe de acordo com os comandos set *setnames , comosetkey

Pankil Shah
fonte