0 Вопрос: Как создать новый объект и отсортировать его по году, названию и событию? [Дубликат]

вопрос создан в Wed, May 8, 2019 12:00 AM

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

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))
dd
    b x y z
1  Hi A 8 1
2 Med D 3 1
3  Hi A 9 1
4 Low C 9 2
    
1217
  1. Для панд можно найти решение здесь .
    2019-01-29 23: 27: 57Z
    19 ответов                              19                         

    Вы можете использовать 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() для более простого /более прямого доступа).

        
    1523
    2018-09-21 13: 42: 37Z
    1. @ Dirk Eddelbuettel Существует ли такой же простой метод для матриц?
      2012-03-27 03: 17: 34Z
    2. Должен работать точно так же, но вы не можете использовать with. Попробуйте M <- matrix(c(1,2,2,2,3,6,4,5), 4, 2, byrow=FALSE, dimnames=list(NULL, c("a","b"))) для создания матрицы M, а затем используйте M[order(M[,"a"],-M[,"b"]),] для упорядочивания в двух столбцах. >
      2012-03-27 12: 41: 29Z
    3. Достаточно просто: dd[ order(-dd[,4], dd[,1]), ], но нельзя использовать with для поднабора на основе имени.
      2012-10-21 14: 34: 07Z
    4. У меня ошибка "недопустимый аргумент для унарного оператора" при выполнении второго примера.
      2013-01-22 23: 01: 47Z
    5. Ошибка «недопустимый аргумент для унарного оператора» возникает при использовании минуса с символьным столбцом. Решите его, обернув столбец в xtfrm, например, dd[ order(-xtfrm(dd[,4]), dd[,1]), ].
      2015-03-24 11: 40: 45Z

    Ваш выбор

    • order от base
    • arrange от dplyr
    • setorder и setorderv от data.table
    • arrange от plyr
    • sort от taRifx
    • orderBy от doBy
    • sortData от Deducer

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

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

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

    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 возвращать «Следующие объекты маскируются из« x (позиция 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)
    

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

    Обратите внимание, что 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)
    

    По-видимому, не совместим с микробенчмарком из-за прикрепления /отсоединения.

    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), но я понимаю, почему Хэдли так поступил из-за проблем, обсуждаемых в вопросе, связанном выше.

        
    425
    2019-04-12 17: 55: 12Z
    1. + 1 для тщательности, хотя я признаю, что нахожу вывод microbenchmark довольно трудным для чтения ...
      2011-07-31 15: 55: 31Z
    2. Функция микробенчмарка ggplot2, описанная выше, теперь доступна как taRifx::autoplot.microbenchmark.
      2012-06-01 01: 23: 01Z
    3. @ AriB.Friedman Каковы интервалы по оси Y /каков масштаб?
      2012-07-30 05: 04: 19Z
    4. @ AME рассмотрим, как b сортируется в образце. По умолчанию используется сортировка по возрастанию, поэтому вы не можете обернуть ее в desc. По возрастанию в обоих: arrange(dd,z,b). По убыванию: arrange(dd,desc(z),desc(b)).
      2013-10-12 10: 16: 56Z
    5. Согласно ?arrange: "# ПРИМЕЧАНИЕ: функции plyr НЕ сохраняют row.names". Это делает превосходную функцию arrange() субоптимальной, если вы хотите сохранить row.names.
      2014-03-10 16: 31: 33Z

    Ответ Дирка великолепен. Также подчеркивается ключевое различие в синтаксисе, используемом для индексации data.frames и 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  поможет вам сделать это.

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

    Давайте изменим контекст из ответа Дирка и скажем, что это часть большого проекта, в котором много имен объектов, и они длинные и значимые; вместо dd он называется quarterlyreport. Он становится:

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

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

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

    Это не то, что вы имели в виду, но вы не заметили это, потому что вы сделали это быстро, и он расположен на странице с похожим кодом. Код не падает (без предупреждения и без ошибок), потому что 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)]
    

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

        
    135
    2012-05-25 21: 42: 51Z
    1. + 1 Это замечательный момент, в котором подробно рассматривается синтаксис R, который меня часто раздражал. Иногда я использую subset(), чтобы избежать необходимости многократно ссылаться на один и тот же объект в рамках одного вызова.
      2012-05-25 20: 45: 05Z
    2. Есть идеи почему они работают по-разному?
      2012-11-26 07: 21: 21Z
    3. @ naught101 Ответы на этот вопрос приведены в data.table FAQ 1.9?
      2012-11-26 08: 04: 59Z
    4. Я полагаю, что вы также можете добавить новую функцию setorder здесь, так как в этом потоке мы отправляем все дупы типа order.
      2015-01-08 19: 18: 19Z

    Здесь есть много отличных ответов, но 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
    
        
    113
    2014-02-18 21: 29: 25Z
    1. Принятый ответ не работает, когда мои столбцы имеют тип или фактор типа (или что-то в этом роде), и я хочу отсортировать по убыванию для этого столбца фактора, за которым следует столбец целых чисел по возрастанию. Но это работает просто отлично! Спасибо!
      2014-02-22 18: 36: 52Z
    2. Почему "только"? Я нахожу файл data.table dd[order(-z, b)] довольно простым в использовании и запоминаемом.
      2014-03-19 11: 11: 38Z
    3. Согласен, между этими двумя методами не так уж много, и data.table является огромным вкладом в R и во многих других отношениях. Я полагаю, что для меня это может быть связано с тем, что в этом случае наличие одного меньшего набора скобок (или одного меньшего типа скобок) уменьшает когнитивную нагрузку лишь на едва заметную величину.
      2014-03-19 17: 13: 59Z
    4. Для меня все сводится к тому, что arrange() является полностью декларативным, а dd[order(-z, b)] - нет.
      2015-05-29 13: 12: 07Z

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

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

    Данные:

    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.table Синтаксис DT[order(...)] был ~ 10x быстрее, чем самый быстрый из других методов (dplyr), при этом потребляя такой же объем памяти, что и dplyr.

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

    функции data.table:

    Скорость:

      Порядок
    • data.table очень быстрый, потому что он реализует радикальный порядок .

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

    Память:

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

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

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

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

    Другие функции:

    1. Он поддерживает integer, logical, numeric, character и даже bit64::integer64.

        

      Обратите внимание, что все классы factor, Date, POSIXct и т. д. относятся к типам integer/numeric с дополнительными атрибутами и, следовательно, также поддерживаются.

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

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

    75
    2017-05-23 10: 31: 37Z
    1. Спасибо за этот очень поучительный ответ о data.table. Хотя я не понимаю, что такое «пиковая память» и как вы ее рассчитали. Не могли бы вы объяснить, пожалуйста? Спасибо!
      2015-06-30 14: 32: 54Z
    2. Я использовал Инструменты - > выделения и сообщил размер «Все кучи и выделения виртуальной машины».
      2015-06-30 14: 55: 01Z
    3. @ Арун Ссылка инструментов в вашем комментарии не работает. Хотите опубликовать обновление?
      2016-03-30 15: 03: 24Z
    4. @ MichaelChirico Вот ссылка на информацию об инструментах, изготовленных Apple: developer.apple.com/library/content/documentation/…
      2017-07-17 09: 25: 08Z

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

    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
    
        
    64
    2016-08-24 14: 49: 59Z
    1. Смотрите мой ответ для сравнительного анализа алгоритма, используемого в этой функции.
      2012-07-12 14: 07: 51Z

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

    library(doBy)
    dd <- orderBy(~-z+b, data=dd)
    
        
    35
    2010-01-19 20: 44: 38Z

    Предположим, у вас есть 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 060035099115062 0600350991150625050505011001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 "электронная     

    33
    2011-05-26 15: 21: 27Z

    В качестве альтернативы можно использовать пакет Deducer

    A     
    26
    2009-08-20 19: 43: 30Z

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

        
    26
    2010-03-08 23: 30: 37Z
    1. MJM, спасибо за указание на этот пакет. Это невероятно гибко, и потому, что половина моей работы уже сделана путем извлечения из баз данных sql, это проще, чем изучать большую часть R, чем интуитивный синтаксис.
      2010-07-29 05: 31: 19Z

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

    y

    Единственная причина, по которой работает этот пример, заключается в том, что z сортируется по

    library(Deducer)
    dd<- sortData(dd,c("z","b"),increasing= c(FALSE,TRUE))
    
    , а не по столбцу с именем 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),]
    

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

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

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

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

    databyage = my.data[order(my.data$age),]
    
    может оказаться полезной. do.call     
    15
    2014-05-13 22: 53: 25Z
    1. Этот синтаксис работает, если вы храните ваши данные в data.table вместо data.frame: data.frame Это работает, потому что имена столбцов доступны внутри [ ] скобки.
      2013-09-02 19: 34: 01Z
    2. Я не думаю, что здесь необходимо понизить голосование, но я не думаю, что это добавляет много к вопросу , особенно с учетом существующий набор ответов, некоторые из которых уже содержат требование с Rs, чтобы использовать 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
      
      .
      2014-02-14 11: 16: 52Z
    3. upvote для require(data.table); my.dt <- data.table(my.data); my.dt[order(age)] это делает короткую работу по сортировке многоколоночного фрейма данных. Просто data.frame и получится красивый каскадный вид.
      2016-05-25 04: 28: 53Z

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

    with     
    14
    2011-05-26 15: 08: 39Z

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

    Использование $ и do.call

    do.call(sort, mydf.obj)

    dplyr

    Просто используйте

    dd <- dd[with(dd, order(-z, b)), ] 
    
    , который является стандартной оценочной версией для dplyr. data.table

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

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

    data.table

    library(dplyr)
    library(data.table)
    
        
    14
    2016-02-05 21: 11: 52Z

    Аранжировка () в dplyer - мой любимый вариант. Используйте оператор трубы и переходите от наименее важного к наиболее важному аспекту

    arrange_     
    8
    2018-10-29 16: 56: 46Z

    Для полноты картины: вы также можете использовать функцию 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)
    
    :
    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
    

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

    dd1 <- dd %>%
        arrange(z) %>%
        arrange(desc(x))
    
        
    5
    2015-08-07 04: 03: 34Z
    1. странно добавлять сравнение производительности, когда ваш метод самый медленный ... в любом случае сомнительно значение использования эталона для 4-х рядов sortByCol()
      2016-03-30 14: 58: 47Z

    Точно так же, как механические сортировщики карт давным-давно, сначала сортируйте по наименее значимому ключу, затем по следующему наиболее значимому и т. д. Библиотека не требуется, работает с любым количеством клавиш и любой комбинацией восходящих и нисходящих клавиш. р> 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
    

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

        
    4
    2015-01-15 04: 28: 25Z

    Другой вариант, использующий пакет

    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
    
    : data.frame     
    3
    2018-05-01 10: 18: 19Z

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

     dd <- dd[order(dd$b, decreasing = FALSE),]
    
    , чтобы сделать это простым способом:
    dd <- dd[order(dd$z, decreasing = TRUE),]
    

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

    функция dfOrder из пакета «psych» р>     

    2
    2018-10-24 22: 32: 43Z

    Просто ради полноты, поскольку о сортировке по номерам столбцов сказано немногое ... Можно с уверенностью утверждать, что это часто нежелательно (поскольку порядок столбцов может измениться, что ведет к ошибкам). ), но в некоторых конкретных ситуациях (когда, например, вам нужна быстрая работа, и нет риска изменить порядок столбцов), это может быть наиболее разумно, особенно при работе с большим количеством столбцов. р>

    В этом случае на помощь приходит

    > 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
    
    : psych     
    2
    2019-04-11 03: 58: 42Z
    dfOrder(myDf, columnIndices)
    
источник размещен Вот