Een dataframe sorteren op meerdere kolom(men)

Ik wil een data.frame sorteren op meerdere kolommen. Met het onderstaande data.frame wil ik bijvoorbeeld sorteren op kolom z(aflopend) en vervolgens op kolom b(oplopend):

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

Antwoord 1, autoriteit 100%

Je kunt de order()direct functioneren zonder toevlucht te nemen tot add-on tools — zie dit eenvoudigere antwoord dat een truc gebruikt vanaf de bovenkant van de example(order)code:

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

Zo’n 2+ jaar later bewerken:Er werd zojuist gevraagd hoe dit te doen per kolomindex. Het antwoord is om eenvoudig de gewenste sorteerkolom(men) door te geven aan de functie 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> 

in plaats van de naam van de kolom te gebruiken (en with()voor eenvoudigere/directere toegang).


Antwoord 2, autoriteit 31%

Uw keuzes

  • orderbij base
  • arrangevan dplyr
  • setorderen setordervvan data.table
  • arrangevan plyr
  • sortvan taRifx
  • orderByvan doBy
  • sortDatavan Deducer

Meestal moet u de oplossingen dplyrof data.tablegebruiken, tenzij het hebben van geen afhankelijkheden belangrijk is, in welk geval base::order.


Ik heb onlangs sort.data.frame aan een CRAN-pakket toegevoegd, waardoor het klasse-compatibel is, zoals hier wordt besproken:
Beste manier om generieke/methode-consistentie voor sorteren te creëren .data.frame?

Daarom kunt u, gezien de data.frame dd, als volgt sorteren:

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 )

Als u een van de oorspronkelijke auteurs van deze functie bent, neem dan contact met mij op. Discussie over het publieke domein vindt u hier: https://chat.stackoverflow.com/transcript/message/1094290 #1094290


Je kunt ook de functie arrange()van plyrgebruiken, zoals Hadley in de bovenstaande thread aangaf:

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

Benchmarks: merk op dat ik elk pakket in een nieuwe R-sessie heb geladen, omdat er veel conflicten waren. Met name het laden van het doBy-pakket zorgt ervoor dat sortretourneert “De volgende object(en) zijn gemaskeerd vanaf ‘x (positie 17)’: b, x, y, z”, en het laden van het Deducer-pakket overschrijft sort.data.framevan Kevin Wright of het taRifx-pakket.

#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
)

Mediane tijden:

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

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

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

Mediane tijd: 1.567

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

Mediane tijd: 862

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

Mediane tijd: 1.694

Houd er rekening mee dat doBy veel tijd nodig heeft om het pakket te laden.

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

Kan Deducer niet laden. Heeft JGR-console nodig.

esort <- function(x, sortvar, ...) {
attach(x)
x <- x[with(x,order(sortvar,...)),]
return(x)
detach(x)
}
microbenchmark(esort(dd, -z, b),times=1000)

Lijkt niet compatibel met microbenchmark vanwege het bevestigen/loskoppelen.


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))

(lijnen lopen van onderste kwartiel naar bovenste kwartiel, punt is de mediaan)


Gezien deze resultaten en het afwegen van eenvoud versus snelheid, zou ik de knipoog moeten geven naar arrangein het plyr-pakket. Het heeft een eenvoudige syntaxis en is toch bijna net zo snel als de basis R-commando’s met hun ingewikkelde machinaties. Typisch briljant Hadley Wickham-werk. Mijn enige klacht is dat het de standaard R-nomenclatuur overtreedt waarbij het sorteren van objecten wordt aangeroepen door sort(object), maar ik begrijp waarom Hadley het op die manier deed vanwege problemen die zijn besproken in de vraag die hierboven is gekoppeld.


Antwoord 3, autoriteit 9%

Dirks antwoord is geweldig. Het benadrukt ook een belangrijk verschil in de syntaxis die wordt gebruikt voor het indexeren van data.frames en 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)]

Het verschil tussen de twee oproepen is klein, maar het kan belangrijke gevolgen hebben. Vooral als je productiecode schrijft en/of je bezighoudt met correctheid in je onderzoek, kun je het beste onnodige herhaling van variabelenamen vermijden. data.table
helpt je hierbij.

Hier is een voorbeeld van hoe herhaling van variabelenamen u in de problemen kan brengen:

Laten we de context van Dirks antwoord veranderen en zeggen dat dit onderdeel is van een groter project waar veel objectnamen zijn en die lang en betekenisvol zijn; in plaats van ddwordt het quarterlyreportgenoemd. Het wordt:

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

Ok, prima. Niets mis mee. Vervolgens vraagt je baas je om het rapport van het afgelopen kwartaal in het rapport op te nemen. Je doorloopt je code, voegt op verschillende plaatsen een object lastquarterlyreporttoe en op de een of andere manier (hoe in godsnaam?) kom je op dit uit:

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

Dat is niet wat je bedoelde, maar je zag het niet omdat je het snel deed en het is genesteld op een pagina met vergelijkbare code. De code valt niet om (geen waarschuwing en geen fout) omdat R denkt dat dit is wat je bedoelde. Je zou hopen dat degene die je rapport leest het ziet, maar misschien ook niet. Als je veel met programmeertalen werkt, is deze situatie misschien maar al te bekend. Het was een “typfout”, zult u zeggen. Ik zal de “typfout” herstellen die je tegen je baas zegt.

in data.tableWe zijn bezorgd over kleine details zoals deze. Dus we hebben iets eenvoudigs gedaan om te voorkomen dat ze twee keer variabele namen typen. Iets heel eenvoudigs. iwordt geëvalueerd in het kader van ddal automatisch. U hebt niet with()nodig.

in plaats van

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

Het is gewoon

dd[order(-z, b)]

en in plaats van

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

Het is gewoon

quarterlyreport[order(-z,b)]

Het is een heel klein verschil, maar het kan gewoon je nek op een dag redden. Bij het afwegen van de verschillende antwoorden op deze vraag, overweeg dan rekening met het tellen van de herhalingen van variabele namen als een van uw criteria bij het bepalen. Sommige antwoorden hebben nogal wat herhalingen, anderen hebben er geen.


Antwoord 4, Autoriteit 8%

Er zijn hier veel uitstekende antwoorden, maar Delyr geeft de enige syntaxis die ik snel en gemakkelijk kan onthouden (en zo Gebruik nu heel vaak):

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)

Voor het probleem van de OP:

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

Antwoord 5, autoriteit 5%

Het R-pakket data.tablebiedt zowel snelleals geheugenefficiënteordening van data.tablesmet een duidelijke syntaxis (een deel waarvan Matt heel mooi in zijn antwoordheeft benadrukt). Sindsdien zijn er nogal wat verbeteringen doorgevoerd en ook een nieuwe functie setorder(). Vanaf v1.9.5+werkt setorder()ook met data.frames.

Eerst maken we een dataset die groot genoeg is en benchmarken we de verschillende genoemde methoden uit andere antwoorden en geven we vervolgens een overzicht van de functies van data.table.

Gegevens:

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)

Benchmarks:

De gerapporteerde timings zijn van het uitvoeren van system.time(...)op deze hieronder getoonde functies. De tijden zijn hieronder weergegeven (in de volgorde van langzaamst naar snelst).

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‘s DT[order(...)]syntaxis was ~10xsneller dan de snelste van andere methoden (dplyr), terwijl ze dezelfde hoeveelheid geheugen verbruiken als dplyr.

  • data.table‘s setorder()was ~14xsneller dan de snelste van andere methoden (dplyr), terwijl het slechts 0,4 GB extra geheugenin beslag neemt. datstaat nu in de volgorde die we nodig hebben (zoals het wordt bijgewerkt door verwijzing).

data.table-functies:

Snelheid:

  • data.table‘s bestellen is extreem snel omdat het implementeert radix bestellen.

  • De syntaxis DT[order(...)]is intern geoptimaliseerd om ook de snelle volgorde van data.tablete gebruiken. U kunt de bekende basis R-syntaxis blijven gebruiken, maar het proces versnellen (en minder geheugen gebruiken).

Geheugen:

  • Meestal hebben we het originele data.frameof data.tableniet nodig na het opnieuw ordenen. Dat wil zeggen, we wijzen het resultaat meestal terug aan hetzelfde object, bijvoorbeeld:

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

    Het probleem is dat hiervoor minimaal twee keer (2x) het geheugen van het originele object nodig is. Om geheugenefficiëntte zijn, biedt data.tabledaarom ook een functie setorder().

    setorder()bestelt data.tablesby reference(ter plaatse) opnieuw, zonder aanvullende exemplaren. Het gebruikt alleen extra geheugen ter grootte van één kolom.

Andere functies:

  1. Het ondersteunt integer, logical, numeric, characteren zelfs bit64::integer64typen.

    Merk op dat factor, Date, POSIXctetc.. klassen allemaal integer/numerictypen eronder met extra attributen en worden daarom ook ondersteund.

  2. In grondtal R kunnen we -niet gebruiken op een tekenvector om in aflopende volgorde op die kolom te sorteren. In plaats daarvan moeten we -xtfrm(.)gebruiken.

    In data.tablekunnen we echter gewoon dat[order(-x)]of setorder(dat, -x).


Antwoord 6, autoriteit 5%

Met deze (zeer nuttige) functie van Kevin Wright, gepost in het gedeelte met tips van de R-wiki, is gemakkelijk te bereiken.

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

Antwoord 7, autoriteit 3%

Stel dat je een data.frameAhebt en je wilt deze sorteren met de kolom xin aflopende volgorde. Roep het gesorteerde data.framenewdata

. op

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

Als je oplopende volgorde wilt, vervang dan "-"door niets. Je kunt zoiets hebben als

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

waar xen zenkele kolommen zijn in data.frameA. Dit betekent sorteer data.frameAop xaflopend, yoplopend en zaflopend.


Antwoord 8, autoriteit 2%

of u kunt het pakket doBy gebruiken

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

Antwoord 9, autoriteit 2%

als SQL voor u vanzelfsprekend is, verwerkt het sqldf-pakket ORDER BYzoals Codd het bedoeld heeft.


Antwoord 10, autoriteit 2%

Als alternatief kunt u het pakket Deducer gebruiken

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

Antwoord 11

Als reactie op een opmerking die in de OP is toegevoegd over het programmatisch sorteren:

Gebruik dplyren data.table

library(dplyr)
library(data.table)

dplyr

Gebruik gewoon arrange_, de standaard evaluatieversie voor 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)

meer info hier: https://cran.r-project.org/web /packages/dplyr/vignettes/nse.html

Het is beter om een formule te gebruiken, omdat deze ook de omgeving vastlegt om een uitdrukking in te evalueren

data.table

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

Antwoord 12

Ik heb geleerd over ordermet het volgende voorbeeld dat me dan lang in de war is:

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

De enige reden waarom deze voorbeeld werkt, is omdat ordersorteren op de vector Age, niet door de kolom met de naam Agein de data frame data.

Om dit te zien maken een identiek gegevensframe met read.tablemet iets verschillende kolomnamen en zonder gebruik te maken van een van de bovenstaande vectoren:

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)

De bovenstaande lijnstructuur voor orderWerkt niet langer omdat er geen vector wordt genoemd Age:

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

De volgende lijn werkt omdat ordersorteert op de kolom AgeIN my.data.

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

Ik dacht dat dit de moeite waard was om te posten, aangezien ik zo lang in de war was door dit voorbeeld. Als dit bericht niet geschikt wordt geacht voor het onderwerp, kan ik het verwijderen.

BEWERK: 13 mei 2014

Hieronder vindt u een algemene manier om een gegevensframe op elke kolom te sorteren zonder kolomnamen op te geven. De onderstaande code laat zien hoe u van links naar rechts of van rechts naar links kunt sorteren. Dit werkt als elke kolom numeriek is. Ik heb het niet geprobeerd met een toegevoegde karakterkolom.

Ik vond de code do.calleen maand of twee geleden in een oud bericht op een andere site, maar pas na uitgebreid en moeilijk zoeken. Ik weet niet zeker of ik die post nu zou kunnen verplaatsen. De huidige thread is de eerste hit voor het bestellen van een data.framein R. Dus ik dacht dat mijn uitgebreide versie van die originele do.call-code misschien wel handig zou zijn.

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

Antwoord 13

Dirk’s antwoord is goed, maar als je de sortering nodig hebt om te blijven bestaan, moet je de sortering weer toepassen op de naam van dat dataframe. Gebruik de voorbeeldcode:

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

Antwoord 14

De arrange() in dplyr is mijn favoriete optie. Gebruik de pijpoperator en ga van het minst belangrijke naar het belangrijkste aspect

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

Antwoord 15

Voor de volledigheid, aangezien er niet veel is gezegd over sorteren op kolomnummers… Er kan zeker worden gesteld dat het vaak niet wenselijk is (omdat de volgorde van de kolommen zou kunnen veranderen, wat de weg vrijmaakt voor fouten ), maar in sommige specifieke situaties (wanneer u bijvoorbeeld een snelle klus moet klaren en er geen risico is dat kolommen van volgorde veranderen), is dit misschien het verstandigste om te doen, vooral als u te maken heeft met grote aantallen kolommen.

In dat geval komt do.call()te hulp:

ind <- do.call(what = "order", args = iris[,c(5,1,2,3)])
iris[ind, ]
##        Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
##    14           4.3         3.0          1.1         0.1     setosa
##    9            4.4         2.9          1.4         0.2     setosa
##    39           4.4         3.0          1.3         0.2     setosa
##    43           4.4         3.2          1.3         0.2     setosa
##    42           4.5         2.3          1.3         0.3     setosa
##    4            4.6         3.1          1.5         0.2     setosa
##    48           4.6         3.2          1.4         0.2     setosa
##    7            4.6         3.4          1.4         0.3     setosa
##    (...)

Antwoord 16

Net als de mechanische kaartsorteerders van lang geleden, sorteer je eerst op de minst significante sleutel, dan de volgende meest significante, enz. Geen bibliotheek vereist, werkt met een willekeurig aantal sleutels en elke combinatie van oplopende en aflopende sleutels.

p>

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

Nu zijn we klaar om de belangrijkste sleutel te doen. De sortering is stabiel en eventuele banden in de belangrijkste sleutel zijn al opgelost.

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

Dit is misschien niet de snelste, maar het is zeker eenvoudig en betrouwbaar


Antwoord 17

Voor de volledigheid: je kunt ook de functie sortByCol()uit het pakket BBmiscgebruiken:

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

Prestatievergelijking:

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

Antwoord 18

Ik worstelde met de bovenstaande oplossingen toen ik mijn bestelproces voor n kolommen wilde automatiseren, waarvan de kolomnamen elke keer anders konden zijn. Ik vond een super handige functie uit het psychpakket om dit op een eenvoudige manier te doen:

dfOrder(myDf, columnIndices)

waarbij columnIndicesindexen zijn van een of meer kolommen, in de volgorde waarin u ze wilt sorteren. Meer informatie hier:

dfOrder-functie uit het ‘psych’-pakket


Antwoord 19

Een ander alternatief, met het pakket 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

Other episodes