Сортировка строк в data.table в порядке убывания по строковому ключу `order (-x, v)` дает ошибку в data.table 1.9.4 или ранее

125

Скажем , у меня есть следующие data.tableв R:

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

Я хочу упорядочить его по двум столбцам (например, столбцам xи v). Я использовал это:

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

Но теперь я хочу отсортировать его x(в порядке убывания) и получить следующий код:

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

Поэтому я думаю, что эта ошибка связана с тем, что class(DT$x)=character. Не могли бы вы дать мне какое-нибудь предложение по решению этой проблемы?

Я знаю, что могу использовать DT[order(x,decreasing=TRUE)], но я хочу знать синтаксис для сортировки по нескольким столбцам, используя оба способа (некоторые уменьшаются, некоторые увеличиваются) одновременно.

Обратите внимание, что если вы используете DT[order(-y,v)]результат, все в порядке, но если вы используете, DT[order(-x,v)]возникает ошибка. Итак, мой вопрос: как решить эту ошибку?

nhern121
источник
6
Интересный вопрос, но если вы работаете с большими наборами данных, вам, вероятно, следует установить ключи для своих data.tables. Ключи размещают ваши данные в таком порядке, который максимизирует последующее индексирование, разбиение на подмножества, агрегирование по группам и т. Д. Возможно, это не ваш предпочтительный формат для печати данных, но часто это небольшая плата за скорость, которую он дает вам ,
Джош О'Брайен,
Однако мне кажется, что DT[order(-x)]это не эквивалентное утверждение, setorder(DT, -x)потому что на setorder()самом деле действует, DTа другое - нет. Эквивалентными операторами были бы DT <- DT [order (-x)] setorder (DT, -x) Я новичок в R, поэтому исправьте, если я ошибаюсь.
jeromeResearch
@jerome Вы правы. Панкил не сказал, что они эквивалентны, так что я думаю, что все в порядке.
Фрэнк
1
Я согласен с @smci, что редактирование заголовка имеет смысл здесь, хотя я бы изменил его, чтобы указать, что этот вопрос больше не актуален, например, добавив в заголовок «in data.table 1.9.4 или ранее», чтобы люди не продолжайте приземляться здесь от Google, ожидая чего-то еще. Я сделал это с одним из моих вопросов stackoverflow.com/questions/30035939/…
Фрэнк
1
Nestorggh, пожалуйста, не откатывайте новое название, если вы не можете его улучшить. «Сортировка строк в data.table» почти ничего не говорит о том, что базовая функциональность была для придурков. В заголовке должна быть указана ваша реальная проблема (несколько ключей, один из которых - порядок удаления). Также важно, что это была известная проблема в версии 1.9.4 и ранее и больше не является проблемой.
smci

Ответы:

144

Обновить

data.table v1.9.6 + теперь поддерживает исходную попытку OP, и следующий ответ больше не нужен.


Вы можете использовать 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
Мэтью Плурд
источник
1
Как указано ниже @PankilShah, это было исправлено в течение некоторого времени, и исходный подход OP теперь работает должным образом. Я не смог найти коммит, так как он был исправлен на уровне C, и я не знаю, что искать.
MichaelChirico
1
Хорошо, спасибо. Кажется маловероятным, что здесь кто-то окажется ... но, с другой стороны, я сам оказался здесь из-за того, что погуглил что-то неясное.
MichaelChirico
@MichaelChirico на самом деле, я обычно получаю голоса за этот ответ, поэтому я очень рад, что вы указали на это. На самом деле я не являюсь пользователем data.table и не успеваю за его развитием.
Мэтью Плурд,
Это очень полезно указать фактический номер версии (1.9.6?), Так что мы не должны идти охотиться в архивах NEWS.md .
smci
23

Вы можете использовать только -числовые записи, поэтому вы можете использовать уменьшение и отрицание тех, которые хотите, в порядке возрастания:

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
Джеймс
источник
3
Мне нравится этот способ, если у вас нет двух characterстолбцов, и вы хотите отсортировать один по возрастанию, а другой по убыванию.
Matthew Plourde,
1
@mplourde Я думаю, вы можете объединить свое решение с этим, чтобы решить поставленную вами проблему. Например, вы можете поставить: DT[order(x,-rank(w),decreasing=TRUE)]при этом xи wоба являются символьными столбцами. Спасибо!
nhern121
17

DT[order(-x)]работает как положено. У меня data.table версии 1.9.4. Возможно, это было исправлено в последней версии.
Кроме того, я предлагаю setorder(DT, -x)синтаксис, соответствующий командам set *, например setnames,setkey

Панкил Шах
источник