Сортировка таблицы данных по возрастанию/убыванию

У меня есть data.table с примерно 3 миллионами строк и 40 столбцов. Я хотел бы отсортировать эту таблицу по убыванию в пределах групп, таких как следующий код sql mock:

sort by ascending Year, ascending MemberID, descending Month 

Есть ли эквивалентный способ в data.table для этого? Пока я должен разбить его на 2 шага:

setkey(X, Year, MemberID)

Это очень быстро и занимает всего несколько секунд.

X <- X[,.SD[order(-Month)],by=list(Year, MemberID)]

Этот шаг занимает намного больше времени (5 минут).

Обновление: Кто-то сделал комментарий, чтобы сделать X <- X[sort(Year, MemberID, -Month)], а затем удален. Этот подход выглядит намного быстрее:

user  system elapsed 
5.560  11.242  66.236 

Мой подход: setkey(), затем order (-Month)

   user  system elapsed 
816.144   9.648 848.798 

Теперь мой вопрос: если я хочу обобщить Year, MemberId и Month после сортировки (Year, MemberID, Month), распознает ли порядок данных? data.table?

Обновление 2: ответ Мэтью Доуле:

После установки с помощью Year, MemberID и Month у меня все еще есть несколько записей для каждой группы. Я хотел бы обобщить для каждой из групп. Я имел в виду: если я использую X [order (Year, MemberID, Month)], то суммирование использует функции бинарного поиска data.table:

monthly.X <- X[, lapply(.SD[], sum), by = list(Year, MemberID, Month)]

Обновление 3: Мэтью D предложил несколько подходов. Время выполнения для первого подхода выполняется быстрее, чем метод order():

   user  system elapsed 
  7.910   7.750  53.916 

Мэтью: меня удивляло то, что преобразование знака месяца занимает большую часть времени. Без него функция setkey быстро пылает.

Ответ 1

Обновление 5 июня 2014 года:

В текущей версии версии data.table v1.9.3 реализованы две новые функции: setorder и setorderv, что делает именно то, что вам нужно. Эти функции переупорядочивают data.table по ссылке с возможностью выбора либо по возрастанию, либо по убыванию в каждом столбце для заказа. Для получения дополнительной информации посетите ?setorder.

Кроме того, DT[order(.)] также по умолчанию оптимизирован для использования data.table внутреннего быстрого порядка вместо base:::order. Это, в отличие от setorder, сделает всю копию данных и, следовательно, будет менее эффективной с точки зрения памяти, но будет по-прежнему на порядок быстрее, чем при использовании базового порядка.

Ориентиры:

Здесь приведено описание разности скоростей с помощью setorder, внутреннего быстрого порядка данных .table и с base:::order:

require(data.table) ## 1.9.3
set.seed(1L)
DT <- data.table(Year     = sample(1950:2000, 3e6, TRUE), 
                 memberID = sample(paste0("V", 1:1e4), 3e6, TRUE), 
                 month    = sample(12, 3e6, TRUE))

## using base:::order
system.time(ans1 <- DT[base:::order(Year, memberID, -month)])
#   user  system elapsed 
# 76.909   0.262  81.266 

## optimised to use data.table fast order
system.time(ans2 <- DT[order(Year, memberID, -month)])
#   user  system elapsed 
#  0.985   0.030   1.027

## reorders by reference
system.time(setorder(DT, Year, memberID, -month))
#   user  system elapsed 
#  0.585   0.013   0.600 

## or alternatively
## setorderv(DT, c("Year", "memberID", "month"), c(1,1,-1))

## are they equal?
identical(ans2, DT)    # [1] TRUE
identical(ans1, ans2)  # [1] TRUE

В этих данных контрольные показатели показывают, что порядок данных .table примерно ~ 79x быстрее, чем base:::order и setorder ~ 135x быстрее, чем base:::order здесь.

data.table всегда сортирует/заказывает в C-locale. Если вам нужно будет заказать другой язык, только тогда вам нужно прибегнуть к использованию DT[base:::order(.)].

Все эти новые оптимизации и функции вместе составляют FR # 2405. добавлена ​​поддержка bit64:: integer64.


ПРИМЕЧАНИЕ. Пожалуйста, обратитесь к истории/ревизиям для более раннего ответа и обновлений.

Ответ 2

Комментарий был мой, поэтому я отправлю ответ. Я удалил его, потому что не мог проверить, соответствует ли он тому, что у вас уже было. Рад это слышать быстрее.

X <- X[order(Year, MemberID, -Month)]

Подведение итогов не должно зависеть от порядка ваших строк.