Как отсортировать фрейм данных по нескольким столбцам?

Я хочу отсортировать data.frame по нескольким столбцам. Например, с data.frame ниже, я хотел бы отсортировать по столбцуz (по убыванию) затем по столбцуb (по возрастанию):

dd 
 cs9530 янв. 2019 г., 00:27
Для панд, решение может быть найденоВот.

Ответы на вопрос(18)

се, используемом для индексации.data.frameс иdata.tables:

## The data.frame way
dd[with(dd, order(-z, b)), ]

## The data.table way: (7 fewer characters, but that's not the important bit)
dd[order(-z, b)]

Разница между двумя вызовами невелика, но она может иметь важные последствия. Особенно, если вы пишете производственный код и / или обеспокоены правильностью своих исследований, это 'Лучше всего избегать ненужного повторения имен переменных.data.table поможет вам сделать это.

Вот'Вот пример того, как повторение имен переменных может привести к неприятностям:

Позволять'изменить контекст с Диркаs ответьте, и скажите, что это часть более крупного проекта, в котором много имен объектов, и они длинные и значимые; вместоdd Это'называетсяquarterlyreport, Это становится :

quarterlyreport[with(quarterlyreport,order(-z,b)),]

Хорошо. В этом нет ничего плохого. Затем ваш босс просит вас включить последнюю четвертьотчет в отчете. Вы идете по своему коду, добавляя объектlastquarterlyreport в разных местах и каким-то образом (как на земле?) вы в конечном итоге с этим:

quarterlyreport[with(lastquarterlyreport,order(-z,b)),]

Это нет, что ты имел в виду, но ты не сделалне заметить, потому что ты сделал это быстро иs расположен на странице с похожим кодом. Код нене падает (без предупреждения и без ошибки), потому что R думает, что это то, что вы имели в виду. Вы'Я надеюсь, что тот, кто читает ваш доклад, заметит его, но, возможно, они нет. Если вы много работаете с языками программирования, то эта ситуация может быть всем знакома. Это был "опечатка" вы'скажу. Я'исправлюопечатка" вы'скажу своему боссу.

Вdata.table мы'обеспокоены мелкими деталями, как это. Итак, мымы сделали что-то простое, чтобы не вводить имена переменных дважды. Нечто очень простое.i оценивается в рамкахdd уже, автоматически. Ты нене нужноwith() совсем.

Вместо

dd[with(dd, order(-z, b)), ]

Это'просто

dd[order(-z, b)]

И вместо

quarterlyreport[with(lastquarterlyreport,order(-z,b)),]

Это'просто

quarterlyreport[order(-z,b)]

Это'Это очень маленькая разница, но это может спасти вашу шею в один прекрасный день. При взвешивании различных ответов на этот вопрос рассмотрите возможность считать повторения имен переменных одним из ваших критериев при принятии решения. Некоторые ответы имеют много повторений, другие нет.

 naught10126 нояб. 2012 г., 08:21
Любая идеяЗачем они работают по-разному?
 Matt Dowle26 нояб. 2012 г., 09:04
@ naught101 Есть ли ответ на этот вопрос в data.table FAQ 1.9?
 Josh O'Brien25 мая 2012 г., 22:45
+1 Это замечательный момент, и подробно рассказывается о R 'Синтаксис, который часто раздражал меня. Я иногда используюsubset() просто чтобы избежать необходимости многократно ссылаться на один и тот же объект в течение одного вызова.
 David Arenburg08 янв. 2015 г., 20:18
Я думаю, вы могли бы добавить новыйsetorder функция здесь, так как этот поток, куда мы отправляем всеorder типа дупс.
Ваш выборorder отbasearrange отdplyrsetorder а такжеsetorderv отdata.tablearrange отplyrsort отtaRifxorderBy отdoBysortData отDeducer

dplyr или жеdata.table Решения, если нет наличия зависимостей, важны, и в этом случае используйте.base::order

Недавно я добавил sort.data.frame в пакет CRAN, сделав его совместимым с классом, как обсуждалось здесь:Лучший способ создать универсальный / метод согласованности для sort.data.frame?

Поэтому, учитывая data.frame dd, вы можете сортировать следующим образом:

dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
library(taRifx)
sort(dd, f= ~ -z + b )

Если вы являетесь одним из авторов этой функции, свяжитесь со мной. Дискуссия в отношении публичности является здесь:http://chat.stackoverflow.com/transcript/message/1094290#1094290

Вы также можете использоватьarrange() функция отplyr как Хэдли указал в вышеупомянутой теме:

library(plyr)
arrange(dd,desc(z),b)

Тесты: обратите внимание, что я загрузил каждый пакет в новом сеансе R, так как было много конфликтов. В частности, загрузка пакета doBy вызываетsort возвращать "Следующие объекты замаскированы изх (позиция 17) ': b, x, y, z "и загрузка пакета Deducer перезаписываетsort.data.frame от Кевина Райта или пакета taRifx.

#Load each time
dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
library(microbenchmark)

# Reload R between benchmarks
microbenchmark(dd[with(dd, order(-z, b)), ] ,
    dd[order(-dd$z, dd$b),],
    times=1000
)

Среднее время:

dd[with(dd, order(-z, b)), ] +778

dd[order(-dd$z, dd$b),] +788

library(taRifx)
microbenchmark(sort(dd, f= ~-z+b ),times=1000)

Среднее время:1567

library(plyr)
microbenchmark(arrange(dd,desc(z),b),times=1000)

Среднее время:+862

library(doBy)
microbenchmark(orderBy(~-z+b, data=dd),times=1000)

Среднее время:1694

Обратите внимание, что doBy требует много времени для загрузки пакета.

library(Deducer)
microbenchmark(sortData(dd,c("z","b"),increasing= c(FALSE,TRUE)),times=1000)

не мог»сделать дедуцером груз. Требуется консоль JGR.

esort <- function(x, sortvar, ...) {
attach(x)
x <- x[with(x,order(sortvar,...)),]
return(x)
detach(x)
}

microbenchmark(esort(dd, -z, b),times=1000)

Безразлично»t кажется совместимым с микробенчмарком из-за прикрепления / отсоединения.

m <- microbenchmark(
  arrange(dd,desc(z),b),
  sort(dd, f= ~-z+b ),
  dd[with(dd, order(-z, b)), ] ,
  dd[order(-dd$z, dd$b),],
  times=1000
  )

uq <- function(x) { fivenum(x)[4]}  
lq <- function(x) { fivenum(x)[2]}

y_min <- 0 # min(by(m$time,m$expr,lq))
y_max <- max(by(m$time,m$expr,uq)) * 1.05

p <- ggplot(m,aes(x=expr,y=time)) + coord_cartesian(ylim = c( y_min , y_max )) 
p + stat_summary(fun.y=median,fun.ymin = lq, fun.ymax = uq, aes(fill=expr))

(линии простираются от нижнего квартиля до верхнего квартиля, точка - медиана)

Учитывая эти результаты и взвешивая простоту и скорость, яя должен был кивнутьarrange вplyr пакет, Он имеет простой синтаксис и, тем не менее, почти такой же быстрый, как команды base R, с их запутанными махинациями. Типично блестящая работа Хэдли Уикхем. Моя единственная неприятность в том, что она нарушает стандартную номенклатуру R, где сортировка объектов вызываетсяsort(object), но я понимаю, почему Хэдли так поступил из-за проблем, обсуждаемых в вопросе, связанном выше.

 Ari B. Friedman30 июл. 2012 г., 12:43
@ naught101 Ось Y начинается с 0. Масштаб должен быть микросекундами.
 Ben Bolker31 июл. 2011 г., 17:55
+1 за основательность, хотя я признаю, что нахожуmicrobenchmark вывод довольно трудно читать ...
 Ari B. Friedman12 окт. 2013 г., 12:16
@AME посмотри какb сортируется в образце. По умолчанию сортировка по возрастанию, так что вы просто необернуть егоdesc, По возрастанию в обоих:arrange(dd,z,b) , По убыванию в обоих.arrange(dd,desc(z),desc(b))
 Ari B. Friedman02 июл. 2015 г., 13:00
Некоторые из них, которые используютorder может быть немного быстрее, если вы используетеsort.list(x, method=“radix”) вместо.
 Ari B. Friedman01 июн. 2012 г., 03:23
Функция микробенчмарка ggplot2, описанная выше, теперь доступна как.taRifx::autoplot.microbenchmark
 AME12 окт. 2013 г., 08:37
@ AriB.Friedman используя 'организовать»как мы сортируем по возрастанию? Я никогда не вижу примеров сортировки по возрастанию. Я старался 'по возрастанию» вместо 'по убыванию» и это нет работа. Спасибо
 landroni10 мар. 2014 г., 17:31
Согласно : "?arrange# ПРИМЕЧАНИЕ: функции plyr НЕ сохраняют row.names, Это делает отличныйarrange() Функция неоптимальная, если кто-то хочет сохранить.row.names
 naught10130 июл. 2012 г., 07:04
@ AriB.Friedman Каковы интервалы по оси Y / что?масштаб?

sqldf обрабатывает ORDER BY так, как задумал Codd.

 Brandon Bertelsen29 июл. 2010 г., 07:31
MJM, спасибо за указание на этот пакет. Это'это невероятно гибко, и потому, что половина моей работы уже сделана путем извлечения из баз данных sql,легче, чем изучать многое из R 'меньше, чем интуитивный синтаксис.

я узнал оorder со следующим примером, который потом меня долго смущал:

set.seed(1234)

ID        = 1:10
Age       = round(rnorm(10, 50, 1))
diag      = c("Depression", "Bipolar")
Diagnosis = sample(diag, 10, replace=TRUE)

data = data.frame(ID, Age, Diagnosis)

databyAge = data[order(Age),]
databyAge

Единственная причина, по которой этот пример работает, заключается в том, чтоorder сортирует поvector Ageне по названному столбцуAge в .data frame data

Чтобы увидеть это, создайте идентичный фрейм данных, используяread.table с немного разными именами столбцов и без использования любого из перечисленных выше векторов:

my.data <- read.table(text = '

  id age  diagnosis
   1  49 Depression
   2  50 Depression
   3  51 Depression
   4  48 Depression
   5  50 Depression
   6  51    Bipolar
   7  49    Bipolar
   8  49    Bipolar
   9  49    Bipolar
  10  49 Depression

', header = TRUE)

Выше структура линии дляorder больше не работает, потому что нет вектора с именем:age

databyage = my.data[order(age),]

Следующая строка работает, потому чтоorder сортирует по колоннеage в .my.data

databyage = my.data[order(my.data$age),]

Я думал, что это стоит опубликовать, учитывая, насколько я был смущен этим примером так долго. Если это сообщение не считается подходящим для темы, я могу удалить его.

РЕДАКТИРОВАТЬ: 13 мая 2014 г.

Ниже приведен обобщенный способ сортировки фрейма данных по каждому столбцу без указания имен столбцов. Код ниже показывает, как сортировать слева направо или справа налево. Это работает, если каждый столбец числовой. Я не пробовал с добавленным столбцом символов.

Я нашелdo.call кодируйте месяц или два назад в старом посте на другом сайте, но только после обширного и сложного поиска. Я не уверен, что мог бы переместить этот пост сейчас. Настоящая тема является первым хитом для заказаdata.frame вR, Итак, я подумал, что моя расширенная версия этого оригиналаdo.call код может быть полезен.

set.seed(1234)

v1  <- c(0,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,1)
v2  <- c(0,0,0,0, 1,1,1,1, 0,0,0,0, 1,1,1,1)
v3  <- c(0,0,1,1, 0,0,1,1, 0,0,1,1, 0,0,1,1)
v4  <- c(0,1,0,1, 0,1,0,1, 0,1,0,1, 0,1,0,1)

df.1 <- data.frame(v1, v2, v3, v4) 
df.1

rdf.1 <- df.1[sample(nrow(df.1), nrow(df.1), replace = FALSE),]
rdf.1

order.rdf.1 <- rdf.1[do.call(order, as.list(rdf.1)),]
order.rdf.1

order.rdf.2 <- rdf.1[do.call(order, rev(as.list(rdf.1))),]
order.rdf.2

rdf.3 <- data.frame(rdf.1$v2, rdf.1$v4, rdf.1$v3, rdf.1$v1) 
rdf.3

order.rdf.3 <- rdf.1[do.call(order, as.list(rdf.3)),]
order.rdf.3
 AdamO25 мая 2016 г., 06:28
голос заdo.call это делает короткую работу по сортировке многоколоночного фрейма данных. Простоdo.call(sort, mydf.obj) и будет красивый каскадный вид.
 Frank02 сент. 2013 г., 21:34
Этот синтаксис работает, если вы храните ваши данные в data.table вместо data.frame:require(data.table); my.dt
 A5C1D2H2I1M1N2O1R2T114 февр. 2014 г., 12:16
Я неЯ думаю, что здесь необходимо понизить голос, но я не думаю, что это добавляетвопрос под рукой, особенно учитывая существующий набор ответов, некоторые из которых уже отражаютdata.frameс либо использоватьwith или же .$

Еще одна альтернатива, используяrgr пакет:

> library(rgr)
> gx.sort.df(dd, ~ -z+b)
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1

когда хотел автоматизировать процесс заказа для n столбцов, имена столбцов которых могли каждый раз отличаться. Я нашел супер полезную функцию отpsych пакет, чтобы сделать это простым способом:

dfOrder(myDf, columnIndices)

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

Функция dfOrder из 'псих» пакет

рубы и переходите от наименее важного к наиболее важному аспекту

dd1 <- dd %>%
    arrange(z) %>%
    arrange(desc(x))

или вы можете использовать пакет doBy

library(doBy)
dd <- orderBy(~-z+b, data=dd)

Сэта (очень полезная) функция Кевина Райта, размещенный в разделе советов R wiki, это легко достигается.

sort(dd,by = ~ -z + b)
#     b x y z
# 4 Low C 9 2
# 2 Med D 3 1
# 1  Hi A 8 1
# 3  Hi A 9 1
 Ari B. Friedman12 июл. 2012 г., 16:07
Смотрите мой ответ для сравнительного анализа алгоритма, используемого в этой функции.

Здесь много отличных ответов, ноdplyr дает единственный синтаксис, который я могу быстро и легко запомнить (и теперь использую очень часто):

library(dplyr)
# sort mtcars by mpg, ascending... use desc(mpg) for descending
arrange(mtcars, mpg)
# sort mtcars first by mpg, then by cyl, then by wt)
arrange(mtcars , mpg, cyl, wt)

Для ОП 'проблема:

arrange(dd, desc(z),  b)

    b x y z
1 Low C 9 2
2 Med D 3 1
3  Hi A 8 1
4  Hi A 9 1
 Ben19 мар. 2014 г., 18:13
Договорились, естьне много между этими двумя методами, иdata.table огромный вклад вR и во многих других отношениях. Я полагаю, что для меня это может быть то, что в этом случае наличие одного меньшего набора скобок (или одного меньшего типа скобок) уменьшает когнитивную нагрузку лишь на едва заметную величину.
 Matt Dowle19 мар. 2014 г., 12:11
Зачем "только"? Я нахожу data.table'sdd[order(-z, b)] довольно легко использовать и запомнить.
 Saheel Godhane22 февр. 2014 г., 19:36
Принятый ответ не работает, когда мои столбцы имеют тип-фактор (или что-то в этом роде), и я хочу отсортировать по убыванию этот столбец с последующим целочисленным столбцом по возрастанию. Но это работает просто отлично! Спасибо!
 Mullefa29 мая 2015 г., 15:12
Для меня это сводится к тому, чтоarrange() полностью декларативный,dd[order(-z, b)] не является.

Ради полноты: вы также можете использоватьsortByCol() функция отBBmisc пакет:

library(BBmisc)
sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE))
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1

Сравнение производительности:

library(microbenchmark)
microbenchmark(sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE)), times = 100000)
median 202.878

library(plyr)
microbenchmark(arrange(dd,desc(z),b),times=100000)
median 148.758

microbenchmark(dd[with(dd, order(-z, b)), ], times = 100000)
median 115.872
 MichaelChirico30 мар. 2016 г., 16:58
странно добавлять сравнение производительности, когда ваш метод самый медленный ... в любом случае сомнительно значение использования эталона на 4-ряднойdata.frame

Предположим, у вас естьdata.frame A и вы хотите отсортировать его с помощью столбца под названиемx в порядке убывания. Позвоните отсортированоdata.frame newdata

newdata <- A[order(-A$x),]

Если вы хотите восходящий порядок, то замените"-" ни с чем. Вы можете иметь что-то вроде

newdata <- A[order(-A$x, A$y, -A$z),]

гдеx а такжеz некоторые столбцы вdata.frame A, Это значит сортироватьdata.frame A отx по убыванию,y по возрастанию иz по убыванию.

но если вам нужен такой способ, чтобы упорствоватьЯ хочу применить сортировку назад к имени этого фрейма данных. Используя пример кода:

dd <- dd[with(dd, order(-z, b)), ] 
Решение Вопроса

Вы можете использоватьorder() работать напрямую, не прибегая к дополнительным инструментам - посмотрите на этот более простой ответ, который использует хитрость прямо из верхней частиexample(order) код:

R> dd[with(dd, order(-z, b)), ]
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1

Отредактируйте примерно через 2 года: Просто спросили, как это сделать по индексу столбца. Ответ заключается в том, чтобы просто передать нужные столбцы сортировкиorder() функция:

R> dd[order(-dd[,4], dd[,1]), ]
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1
R> 

вместо того, чтобы использовать имя столбца (иwith() для более простого / более прямого доступа).

 René Nyffenegger30 июл. 2014 г., 14:13
Почему этопустой параметр (, ]) необходимо?
 Dirk Eddelbuettel30 июл. 2014 г., 14:39
Потому что вы хотите выбратьвсе столбцы двумерной структуры данных R.
 Richie Cotton24 мар. 2015 г., 12:40
"неверный аргумент унарному оператору ошибка возникает при использовании минуса с символьным столбцом. Решите это, обернув столбец вxtfrm, например .dd[ order(-xtfrm(dd[,4]), dd[,1]), ]
 HattrickNZ31 июл. 2014 г., 00:11
почемуdd[ order(-dd[,4],, ] не действителен илиdd [order (-dd [, 4],] ' в основном почемуdd[,1] требуется? является-dd[,4] не достаточно, если вы просто хотите отсортировать по 1 столбцу?
 Jota27 мар. 2012 г., 05:17
@Dirk Eddelbuettel Есть ли такой же простой метод для матриц?
 dasf12 апр. 2017 г., 13:06
У меня похожая проблема, за исключением того, что мой df имеет более 20 столбцов и должен быть отсортирован по каждому. Я мог бы написать имена столбцов один за другим (например,R> dd[with(dd, order(a,b,c,...,z)), ]), но мне интересно, если естьЭто более простой способ. Можно ли вообще объединить 20 с чем-то аргументовorder в один объект?
 hertzsprung21 окт. 2012 г., 16:30
Как я могу адаптировать это к порядку по индексу столбца, а не по имени столбца?
 Dirk Eddelbuettel27 мар. 2012 г., 14:41
Должен работать так же, но вы можетет использоватьwith, ПытатьсяM
 Dirk Eddelbuettel21 окт. 2012 г., 16:34
Достаточно просто:dd[ order(-dd[,4], dd[,1]), ], но может'т использоватьwith для основанного на имени подмножества.
 Nailgun23 янв. 2013 г., 00:01
Я имею "неверный аргумент унарному оператору ошибка при запуске второго примера.

добавленный в OP для того, как сортировать программно:

С помощьюdplyr а такжеdata.table

library(dplyr)
library(data.table)
dplyr

Просто используйтеarrange_, которая является стандартной оценочной версией для.arrange

df1 <- tbl_df(iris)
#using strings or formula
arrange_(df1, c('Petal.Length', 'Petal.Width'))
arrange_(df1, ~Petal.Length, ~Petal.Width)
    Source: local data frame [150 x 5]

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          (dbl)       (dbl)        (dbl)       (dbl)  (fctr)
1           4.6         3.6          1.0         0.2  setosa
2           4.3         3.0          1.1         0.1  setosa
3           5.8         4.0          1.2         0.2  setosa
4           5.0         3.2          1.2         0.2  setosa
5           4.7         3.2          1.3         0.2  setosa
6           5.4         3.9          1.3         0.4  setosa
7           5.5         3.5          1.3         0.2  setosa
8           4.4         3.0          1.3         0.2  setosa
9           5.0         3.5          1.3         0.3  setosa
10          4.5         2.3          1.3         0.3  setosa
..          ...         ...          ...         ...     ...


#Or using a variable
sortBy <- c('Petal.Length', 'Petal.Width')
arrange_(df1, .dots = sortBy)
    Source: local data frame [150 x 5]

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          (dbl)       (dbl)        (dbl)       (dbl)  (fctr)
1           4.6         3.6          1.0         0.2  setosa
2           4.3         3.0          1.1         0.1  setosa
3           5.8         4.0          1.2         0.2  setosa
4           5.0         3.2          1.2         0.2  setosa
5           4.7         3.2          1.3         0.2  setosa
6           5.5         3.5          1.3         0.2  setosa
7           4.4         3.0          1.3         0.2  setosa
8           4.4         3.2          1.3         0.2  setosa
9           5.0         3.5          1.3         0.3  setosa
10          4.5         2.3          1.3         0.3  setosa
..          ...         ...          ...         ...     ...

#Doing the same operation except sorting Petal.Length in descending order
sortByDesc <- c('desc(Petal.Length)', 'Petal.Width')
arrange_(df1, .dots = sortByDesc)

больше информации здесь:https://cran.r-project.org/web/packages/dplyr/vignettes/nse.html

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

Таблица данных
dt1 <- data.table(iris) #not really required, as you can work directly on your data.frame
sortBy <- c('Petal.Length', 'Petal.Width')
sortType <- c(-1, 1)
setorderv(dt1, sortBy, sortType)
dt1
     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
  1:          7.7         2.6          6.9         2.3 virginica
  2:          7.7         2.8          6.7         2.0 virginica
  3:          7.7         3.8          6.7         2.2 virginica
  4:          7.6         3.0          6.6         2.1 virginica
  5:          7.9         3.8          6.4         2.0 virginica
 ---                                                            
146:          5.4         3.9          1.3         0.4    setosa
147:          5.8         4.0          1.2         0.2    setosa
148:          5.0         3.2          1.2         0.2    setosa
149:          4.3         3.0          1.1         0.1    setosa
150:          4.6         3.6          1.0         0.2    setosa

как механические сортировщики карт давным-давно, сначала сортируют по наименее значимому ключу, затем по следующему наиболее значимому и т. Д. Библиотека не требуется, работает с любым количеством клавиш и любой комбинацией восходящих и нисходящих клавиш.

 dd <- dd[order(dd$b, decreasing = FALSE),]

Теперь мы'готовы сделать самый важный ключ. Сортировка стабильна, и любые связи в наиболее значимом ключе уже разрешены.

dd <- dd[order(dd$z, decreasing = TRUE),]

Это может быть не самым быстрым, но это, безусловно, просто и надежно

Как вариант, используя пакет Deducer

library(Deducer)
dd<- sortData(dd,c("z","b"),increasing= c(FALSE,TRUE))

data.table обеспечивает какбыстро а такжеэффективная память заказdata.tables с прямым синтаксисом (часть которого Мэтт выделил довольно красивов своем ответе). Там было довольно много улучшений, а также новая функцияsetorder() с того времени. От ,v1.9.5+setorder() также работает сdata.frames.

Сначала мы'Я создам набор данных, достаточно большой, и сравню различные методы, упомянутые в других ответах, а затем перечислю особенностиТаблица данных.

Данные:
require(plyr)
require(doBy)
require(data.table)
require(dplyr)
require(taRifx)

set.seed(45L)
dat = data.frame(b = as.factor(sample(c("Hi", "Med", "Low"), 1e8, TRUE)),
                 x = sample(c("A", "D", "C"), 1e8, TRUE),
                 y = sample(100, 1e8, TRUE),
                 z = sample(5, 1e8, TRUE), 
                 stringsAsFactors = FALSE)
тесты:

Время сообщается от запускаsystem.time(...) на эти функции показано ниже. Время приведено в таблице ниже (в порядке от самого медленного до самого быстрого).

orderBy( ~ -z + b, data = dat)     ## doBy
plyr::arrange(dat, desc(z), b)     ## plyr
arrange(dat, desc(z), b)           ## dplyr
sort(dat, f = ~ -z + b)            ## taRifx
dat[with(dat, order(-z, b)), ]     ## base R

# convert to data.table, by reference
setDT(dat)

dat[order(-z, b)]                  ## data.table, base R like syntax
setorder(dat, -z, b)               ## data.table, using setorder()
                                   ## setorder() now also works with data.frames 

# R-session memory usage (BEFORE) = ~2GB (size of 'dat')
# ------------------------------------------------------------
# Package      function    Time (s)  Peak memory   Memory used
# ------------------------------------------------------------
# doBy          orderBy      409.7        6.7 GB        4.7 GB
# taRifx           sort      400.8        6.7 GB        4.7 GB
# plyr          arrange      318.8        5.6 GB        3.6 GB 
# base R          order      299.0        5.6 GB        3.6 GB
# dplyr         arrange       62.7        4.2 GB        2.2 GB
# ------------------------------------------------------------
# data.table      order        6.2        4.2 GB        2.2 GB
# data.table   setorder        4.5        2.4 GB        0.4 GB
# ------------------------------------------------------------

data.tableDT[order(...)] синтаксис был~ 10x быстрее, чем самый быстрый из других методов (dplyr), потребляя столько же памяти, сколько.dplyr

data.tablesetorder() было~ 14x быстрее, чем самый быстрый из других методов (dplyr), принимаявсего 0,4 ГБ дополнительной памяти.dat теперь в том порядке, в котором мы нуждаемся (так как он обновляется по ссылке).

Возможности data.table:

Скорость:

Таблица данных'порядок очень быстрый, потому что он реализуетрадикальный порядок.

СинтаксисDT[order(...)] оптимизировано для внутреннего использованияТаблица данных'Быстрый заказ, а также. Вы можете продолжать использовать знакомый синтаксис base R, но ускорить процесс (и использовать меньше памяти).

Объем памяти:

В большинстве случаев мы нене требует оригиналаdata.frame или жеТаблица данных после переупорядочения. То есть мы обычно присваиваем результат тому же объекту, например:

DF <- DF[order(...)]

Проблема в том, что для этого требуется как минимум вдвое (в 2 раза) объем памяти исходного объекта. Бытьэффективная память,Таблица данных поэтому также предоставляет функцию.setorder()

setorder() реорганизуетdata.tables  (by referenceна месте), не делая дополнительных копий. Используется только дополнительная память, равная размеру одного столбца.

Другие преимущества:

Это поддерживает,,,integerlogicalnumericcharacter и дажеbit64::integer64 типы.

Обратите внимание, что , ,factorDatePOSIXct и т. д. классы все /integernumeric типы внизу с дополнительными атрибутами и поэтому также поддерживаются.

В базе R мы не можем использовать- по символьному вектору для сортировки по этому столбцу в порядке убывания. Вместо этого мы должны использовать.-xtfrm(.)

Однако вТаблица данныхмы можем просто сделать, например,dat[order(-x)] или же .setorder(dat, -x)

 n1k31t417 июл. 2017 г., 11:25
@MichaelChirico Вот ссылка на информацию об инструментах, сделанных Apple:developer.apple.com/library/content/documentation/...
 Julien Navarre30 июн. 2015 г., 16:32
Спасибо за этот очень поучительный ответ о data.table. Хотя я нене понимаю, что такое "пик памяти " и как ты это рассчитал. Не могли бы вы объяснить, пожалуйста? Спасибо !
 MichaelChirico30 мар. 2016 г., 17:03
@ Arun Ссылка на инструменты в вашем комментарии мертва. Хотите опубликовать обновление?
 Arun30 июн. 2015 г., 16:55
я использовалИнструменты -> ассигнования и сообщили "Вся куча и выделение ВМ " размер.

Ваш ответ на вопрос