Bir veri çerçevesini birden çok sütuna göre sıralama


1316

Bir data.frame öğesini birden çok sütuna göre sıralamak istiyorum. Örneğin, aşağıdaki data.frame ile önce sütun z(azalan) sonra sütun b(artan) göre sıralamak istiyorum :

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

Yanıtlar:


1625

Bu order()işlevi, eklenti araçlarına başvurmadan doğrudan kullanabilirsiniz - example(order)kodun hemen üstünden bir hile kullanan bu daha basit cevaba bakın :

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

Birkaç yıl sonra düzenleme: Sadece sütun dizini ile nasıl yapılacağı soruldu. Yanıt, istenen sıralama sütun (lar) ını order()işleve geçirmektir :

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> 

sütunun adını kullanmak yerine (ve with()daha kolay / daha doğrudan erişim için).


@Dirk Eddelbuettel matrisler için benzer basit bir yöntem var mı?
Jota

14
Aynı şekilde çalışmalı ama kullanamazsınız with. M <- matrix(c(1,2,2,2,3,6,4,5), 4, 2, byrow=FALSE, dimnames=list(NULL, c("a","b")))Bir matris oluşturmayı deneyin M, ardından M[order(M[,"a"],-M[,"b"]),]iki sütunda sipariş vermek için kullanın .
Dirk Eddelbuettel

4
Yeterince kolay: dd[ order(-dd[,4], dd[,1]), ]ancak withad tabanlı alt ayarlarda kullanılamaz.
Dirk Eddelbuettel

18
İkinci örneği çalıştırırken "tekli operatöre geçersiz argüman" hatası var.
Nailgun

21
Eksi bir karakter sütunuyla kullandığınızda "tekli işleç için geçersiz argüman" hatası oluşuyor. xtfrmÖrneğin , sütunu sararak çözün dd[ order(-xtfrm(dd[,4]), dd[,1]), ].
Richie Cotton

477

Senin seçimlerin

  • order itibaren base
  • arrange itibaren dplyr
  • setorderve setordervgelendata.table
  • arrange itibaren plyr
  • sort itibaren taRifx
  • orderBy itibaren doBy
  • sortData itibaren Deducer

Çoğunlukla bağımlılıkların olmaması önemli olmadığı sürece dplyrveya data.tableçözümlerini kullanmalısınız, bu durumda kullanın base::order.


Geçenlerde bir CRAN paketine sort.data.frame ekledim, burada tartışıldığı gibi sınıfı uyumlu hale getirdim: sort.data.frame için genel / yöntem tutarlılığı oluşturmanın en iyi yolu?

Bu nedenle, data.frame dd değeri verildiğinde aşağıdaki gibi sıralayabilirsiniz:

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 )

Bu işlevin orijinal yazarlarından biriyseniz, lütfen benimle iletişime geçin. Herkese açık alanlarla ilgili tartışma burada: http://chat.stackoverflow.com/transcript/message/1094290#1094290


Bu arrange()işlevi, plyrHadley'in yukarıdaki iş parçacığında işaret ettiği gibi de kullanabilirsiniz :

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

Deneyler: Çok fazla çakışma olduğu için her paketi yeni bir R oturumuna yüklediğimi unutmayın. Özellikle doBy paketinin yüklenmesi sort"Aşağıdaki nesneler 'x (konum 17)' den maskelenir: b, x, y, z" ve Deducer paketinin yüklenmesi sort.data.frameKevin Wright veya taRifx paketinin üzerine yazılır .

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

Ortalama süreler:

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

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

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

Ortalama süre: 1.567

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

Ortalama süre: 862

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

Ortalama süre: 1,694

DoBy'nin paketi yüklemek için biraz zaman aldığını unutmayın.

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

Deducer yüklenemedi. JGR konsolu gerekir.

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

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

Takma / çıkarma nedeniyle mikrobenç işaretiyle uyumlu görünmüyor.


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

mikrobenchmark çizimi

(çizgiler alt dörtte birlik kısımdan üst dörtte birlik bölgeye uzanır, nokta medyandır)


Bu sonuçları göz önüne alındığında ve basitlik vs hızını ağırlığında, ben selam vermem gerekir arrangeyılında plyrpaketin . Basit bir sözdizimine sahiptir ve kıvrımlı işlemleriyle temel R komutları kadar hızlıdır. Genellikle parlak Hadley Wickham çalışır. Benim tek yakınma, sıralama nesnelerinin çağrıldığı standart R nomenklatürünü kırması sort(object), ancak yukarıda bağlantılı soruda tartışılan sorunlar nedeniyle Hadley'nin neden bu şekilde yaptığını anlıyorum.


3
Yukarıdaki ggplot2 mikrobençmark fonksiyonu şimdi olarak mevcuttur taRifx::autoplot.microbenchmark.
Ari B. Friedman

@ AriB.Friedman Y ekseni aralıkları nedir / ölçek nedir?
naught101

@ naught101 y ekseni 0'da başlar. Ölçek mikrosaniye olmalıdır.
Ari B. Friedman

2
@AME örnekte nasıl sıralandığına bakın b. Varsayılan, artan şekilde sıralanır, bu yüzden onu sarmazsınız desc. Hem Artan: arrange(dd,z,b). Hem Azalan: arrange(dd,desc(z),desc(b)).
Ari B. Friedman

2
?arrangeŞuna göre : "# NOT: plyr işlevleri row.names işlevini korumaz". Bu, arrange()tutmak isterse mükemmel işlevi yetersiz kılar row.names.
2014'te landroni

148

Dirk'ün cevabı harika. Ayrıca, data.frames ve data.tables indeksleme için kullanılan sözdiziminde önemli bir farkı vurgular :

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

İki çağrı arasındaki fark küçüktür, ancak önemli sonuçları olabilir. Özellikle üretim kodu yazarsanız ve / veya araştırmanızda doğrulukla ilgileniyorsanız, değişken adlarının gereksiz yere tekrarlanmasını önlemek en iyisidir. data.table bunu yapmanıza yardımcı olur.

Aşağıda, değişken adlarının tekrarının sizi nasıl sorun haline getirebileceğine ilişkin bir örnek verilmiştir:

Bağlamı Dirk'ün cevabından değiştirelim ve bunun çok sayıda nesne adının olduğu ve uzun ve anlamlı olduğu daha büyük bir projenin parçası olduğunu söyleyelim; yerine dddenir quarterlyreport. O olur :

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

Tamam iyi. Bunda yanlış bir şey yok. Ardından patronunuz sizden son çeyreğin raporunu rapora eklemenizi istiyor. Kodunuzu gözden geçiriyorsunuz lastquarterlyreport, çeşitli yerlere bir nesne ekliyorsunuz ve bir şekilde (nasıl?

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

Kastettiğiniz bu değil, ancak hızlı bir şekilde yaptığınız ve benzer kodlu bir sayfada yer aldığından onu fark etmediniz. Kod düşmüyor (uyarı yok ve hata yok), çünkü R demek istediğiniz şey olduğunu düşünüyor. Raporunuzu kim okursa raporda yer bulacağını umuyorsunuz, ama belki bilmiyorlar. Programlama dilleri ile çok çalışıyorsanız, bu durum tanıdık gelebilir. Söyleyeceğiniz bir "yazım hatası" dı. Patronunuza söyleyeceğiniz "yazım hatasını" düzeltirim.

İçinde data.tablebunun gibi ufak detaylardan endişe duyuyoruz. Bu nedenle, değişken adlarını iki kez yazmaktan kaçınmak için basit bir şey yaptık. Çok basit bir şey. ikapsamında değerlendirilir ddotomatik olarak zaten. Hiç ihtiyacınız yok with().

Onun yerine

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

bu sadece

dd[order(-z, b)]

Ve yerine

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

bu sadece

quarterlyreport[order(-z,b)]

Bu çok küçük bir fark, ama bir gün boynunuzu kurtarabilir. Bu soruya verilen farklı cevapları tartarken, değişken isimlerinin tekrarlarını karar verme kriterlerinizden biri olarak saymayı düşünün. Bazı cevaplar oldukça az, bazıları cevapsız.


9
+1 Bu harika bir nokta ve R'nin beni sık sık rahatsız eden sözdiziminin bir ayrıntısına iniyor. Bazen subset()sadece tek bir çağrıda aynı nesneye tekrar tekrar başvurmak zorunda kalmamak için kullanıyorum .
Josh O'Brien

2
@ naught101 data.table FAQ 1.9 buna cevap veriyor mu?
Matt Dowle

5
setorderBu iş parçacığı tüm ordertip dupes göndermek nerede olduğu gibi yeni işlevi de burada ekleyebilirsiniz sanırım .
David Arenburg

125

Burada çok sayıda mükemmel cevap var, ancak dplyr hızlı ve kolay bir şekilde hatırlayabildiğim tek sözdizimini veriyor (ve şimdi çok sık kullanıyorum):

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)

OP'nin sorunu için:

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

2
Kabul edilen cevap, sütunlarım olduğunda veya tür faktörü (veya bunun gibi bir şey) olduğunda işe yaramaz ve bu faktör sütunu için azalan şekilde sıralamak ve ardından artan şekilde tamsayı sütunu sıralamak istiyorum. Ama bu gayet iyi çalışıyor! Teşekkür ederim!
Saheel Godhane

10
Neden "sadece"? Data.table'ı dd[order(-z, b)]kullanmak oldukça kolay ve hatırlıyorum.
Matt Dowle

2
Anlaşılan, bu iki yöntem arasında fazla bir şey yoktur ve diğer birçok yönden de data.tablebüyük bir katkıdır R. Benim için sanırım, bu durumda daha az sayıda parantez (ya da daha az parantez tipi) olması bilişsel yükü zar zor algılanabilir bir miktarda azaltır.
Ben

7
Benim için arrange()tamamen bildirimsel olan dd[order(-z, b)], değil.
Mullefa

83

R paketi data.table, verilerin hızlı ve bellek açısından verimli bir şekilde sıralanmasını sağlar. Anlaşılır bir sözdizimi ile (Matt'in cevabında oldukça güzel bir şekilde vurgulandığı bir bölüm ). O zamandan beri oldukça fazla iyileştirme ve yeni bir işlev var setorder(). Kaynak v1.9.5+, data.framessetorder() ile de çalışır .

İlk olarak, yeterince büyük bir veri kümesi oluşturacağız ve diğer cevaplardan bahsedilen farklı yöntemleri kıyaslayacağız ve ardından data.table'ın özelliklerini listeleyeceğiz .

Veri:

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)

Testleri:

Bildirilen zamanlamalar system.time(...)aşağıda gösterilen bu işlevler üzerinde çalışmaktadır . Zamanlamalar aşağıda sıralanmıştır (en yavaşdan en hızlıya doğru sırayla).

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'nin DT[order(...)]sözdizimi, diğer yöntemlerden en hızlı olandan ( ) yaklaşık 10 kat daha hızlıdır .dplyrdplyr

  • data.table'ın setorder()oldu ~ 14x daha hızlı diğer yöntemlerle (en hızlı daha dplyrçekerken,) sadece 0.4GB ekstra bellek . datşimdi istediğimiz sırada (referans olarak güncellendiği için).

data.table özellikleri:

hız:

  • data.table'ın sıralaması son derece hızlıdır, çünkü sayı tabanı sıralaması uygular .

  • Sözdizimi data.table'ın hızlı sırasınıDT[order(...)] kullanacak şekilde dahili olarak optimize edilmiştir . Bilindik temel R sözdizimini kullanmaya devam edebilirsiniz, ancak işlemi hızlandırabilirsiniz (ve daha az bellek kullanabilirsiniz).

Hafıza:

  • Çoğu kez, orijinal gerektirmeyen data.frame veya data.table yeniden düzenlenmesi sonra. Yani, sonucu genellikle aynı nesneye geri atarız, örneğin:

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

    Sorun, bunun orijinal nesnenin belleğinin en az iki katı (2x) gerektirmesidir. Bu nedenle bellek verimli olmak için data.table aynı zamanda bir işlev de sağlar setorder().

    setorder()data.tables by reference ( yerinde ), başka kopya oluşturmadan yeniden sıralar . Yalnızca bir sütunun boyutuna eşit fazladan bellek kullanır.

Diğer özellikler:

  1. Bu destekler integer, logical, numeric, characterve hatta bit64::integer64türleri.

    Not olduğunu factor, Date, POSIXctvb .. sınıflar hepsi integer/ numerictürleri ek özelliklerle altında ve bu nedenle de desteklenmektedir.

  2. Temel R'de, -bu sütuna göre azalan sırada sıralamak için bir karakter vektöründe kullanamayız . Bunun yerine kullanmak zorundayız -xtfrm(.).

    Bununla birlikte, data.table içinde , örneğin dat[order(-x)]veya yapabiliriz setorder(dat, -x).


Data.table ile ilgili bu çok eğitici cevap için teşekkürler. Yine de, "zirve bellek" nedir ve nasıl hesapladığınızı anlamıyorum. Açıklayabilir misiniz lütfen? Teşekkür ederim !
Julien Navarre

Ben kullanılan aygıtlar > tahsisleri ve "Tüm yığın ve tahsisini VM" boyutu bildirdi -.
Arun

2
@ Yorumunuzdaki Enstrümanlar bağlantısını kaldırın. Güncelleme yayınlamak ister misiniz?
MichaelChirico

@MichaelChirico Apple tarafından üretilen Enstrümanlar hakkında bilgi için link: developer.apple.com/library/content/documentation/…
n1k31t4


39

veya doBy paketini kullanabilirsiniz

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

39

Varsayalım data.frame Ave xazalan düzen adlı sütunu kullanarak sıralamak istediğinizi varsayalım . Sıralı aradata.frame newdata

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

Artan düzen istiyorsanız "-", hiçbir şeyle değiştirin . Gibi bir şey olabilir

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

Nerede xve zbazı sütunlar bulunmaktadır data.frame A. Bu data.frame A, xazalan, yartan ve zazalan şekilde sıralama anlamına gelir .


32

SQL size doğal olarak gelirse, sqldfpaket ORDER BYCodd'un istediği gibi işler .


7
MJM, bu pakete dikkat çektiğin için teşekkürler. İnanılmaz derecede esnek ve işlerimin yarısı zaten sql veritabanlarından çekilerek yapıldığından, R'lerin çoğunu sezgisel sözdiziminden daha az öğrenmekten daha kolay.
Brandon Bertelsen

31

Alternatif olarak, Deducer paketini kullanarak

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

19

Programlı olarak nasıl sıralanacağı konusunda OP'ye eklenen bir yoruma yanıt olarak:

kullanılması dplyrvedata.table

library(dplyr)
library(data.table)

dplyr

Sadece arrange_Standart Değerlendirme sürümü olan kullanın 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)

daha fazla bilgi burada: https://cran.r-project.org/web/packages/dplyr/vignettes/nse.html

Bir ifadeyi değerlendirmek için çevreyi de yakaladığı için formülü kullanmak daha iyidir

veri tablosu

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

18

Daha ordersonra beni uzun bir süre karıştırdığım aşağıdaki örnekle öğrendim :

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

Çünkü bu örnek çalışan tek nedenidir ordergöre sıralama edilir vector Agedeğil adlandırılmış sütuna göre, Ageiçinde data frame data.

Bunu görmek için read.table, biraz farklı sütun isimleriyle ve yukarıdaki vektörlerden herhangi birini kullanmadan özdeş bir veri çerçevesi oluşturun :

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)

Yukarıdaki çizgi yapısı orderartık çalışmaz çünkü şu şekilde adlandırılmış bir vektör yoktur age:

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

Aşağıdaki satırı çünkü çalışır ordersütun üzerinde türlü agede my.data.

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

Uzun zamandır bu örnekle ne kadar şaşkın olduğum göz önüne alındığında, bunun gönderilmeye değer olduğunu düşündüm. Bu yazı iş parçacığı için uygun kabul edilmezse kaldırabilirim.

EDIT: 13 Mayıs 2014

Aşağıda, sütun adlarını belirtmeden bir veri çerçevesini her sütuna göre sıralamanın genel bir yolu verilmiştir. Aşağıdaki kod soldan sağa veya sağdan sola nasıl sıralanacağını gösterir. Bu, her sütun sayısalsa işe yarar. Eklenen bir karakter sütunu ile denemedim.

do.callKodu bir iki ay önce farklı bir sitedeki eski bir gönderide buldum , ancak sadece kapsamlı ve zor bir aramadan sonra. Bu gönderiyi şimdi değiştirebileceğimden emin değilim. Mevcut diş bir sipariş için ilk isabet data.framein R. Yani, orijinal do.callkodun genişletilmiş versiyonunun yararlı olabileceğini düşündüm .

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

4
Verilerinizi data.frame yerine data.table içinde saklarsanız bu sözdizimi require(data.table); my.dt <- data.table(my.data); my.dt[order(age)]çalışır : Bu, sütun adlarının [] köşeli ayraçları içinde kullanılabilir olması nedeniyle çalışır.
Frank

Ben downvote burada gerekli olduğunu düşünmüyorum, ama hiçbiri bu çok ekler sizce sorusuna özellikle zaten gereksinimi yakalamak bazıları cevaplar, mevcut kümesi dikkate el altında data.frameya kullanımına s withveya $.
A5C1D2H2I1M1N2O1R2T1

1
bunun için oylama, do.callçok sütunlu bir veri çerçevesini sıralamak için kısa bir çalışma yapar. Basitçe do.call(sort, mydf.obj)ve güzel bir çağlayan tür olacak.
AdamO

17

Dirk'un cevabı iyidir, ancak devam etmek için sıralamaya ihtiyacınız varsa, sıralamayı bu veri çerçevesinin adına geri uygulamak istersiniz. Örnek kodu kullanarak:

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

13

Dplyer'deki arrange () benim en sevdiğim seçenektir. Boru operatörünü kullanın ve en az önemli olandan en önemli noktaya geçin

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

7

Sadece tamlık uğruna, sütun sayılarına göre sıralama hakkında çok fazla şey söylenmediğinden ... kesinlikle istenmediği iddia edilebilir (çünkü sütunların sırası değişebilir, hatalara yol açabilir), ancak bazı özel durumlarda (örneğin, hızlı bir iş yapmanız gerektiğinde ve sütun değiştirme düzenleri söz konusu olmadığında), özellikle çok sayıda sütunla uğraşırken yapılacak en mantıklı şey olabilir.

Bu durumda do.call()kurtarmaya gelir:

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

6

Tamlık uğruna: sortByCol()işlevi BBmiscpaketten de kullanabilirsiniz :

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

Performans karşılaştırması:

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

4
yönteminiz en yavaş olduğunda bir performans karşılaştırması eklemek için garip ... yine de 4 satırda bir ölçüt kullanmanın değeri şüphelidata.frame
MichaelChirico

5

Tıpkı uzun zaman önce mekanik kart sıralayıcıları gibi, önce en az önemli tuşa, sonra bir sonraki en önemli, vb.

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

Şimdi en önemli anahtarı yapmaya hazırız. Sıralama sabittir ve en önemli anahtardaki bağlar zaten çözülmüştür.

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

Bu en hızlı olmayabilir, ancak kesinlikle basit ve güvenilirdir


4

rgrPaketi kullanan başka bir alternatif :

> 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

4

Sütun adları her seferinde farklı olabilecek n sütun için sipariş sürecimi otomatikleştirmek istediğimde yukarıdaki çözümlerle uğraşıyordum. Bunu psychbasit bir şekilde yapmak için paketten süper yararlı bir işlev buldum :

dfOrder(myDf, columnIndices)

nerede columnIndicessıralamak istediğiniz sırayla, bir veya daha fazla sütunun endeksleridir. Daha fazla bilgi burada:

'psych' paketinden dfOrder işlevi

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.