كيفية فرز dataframe حسب العمود (الأعمدة)؟


6 Answers

اختياراتك

  • order من base
  • arrange من dplyr
  • setorder و setorderv من data.table
  • arrange من plyr
  • sort من taRifx
  • orderBy من خلال doBy
  • sortData من Deducer

في معظم الأحيان يجب عليك استخدام حلول data.table أو 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 للرجوع "الكائن (الأقنعة) التالية مقنعة من 'x (الموضع 17)': b ، x ، y ، z" ، وتحميل حزمة sort.data.frame من Kevin رايت أو حزمة 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)

الوقت الوسطي: 1،567

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)

لا يمكن أن تجعل تحميل Deducer. يحتاج إلى وحدة تحكم JGR.

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

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

لا يبدو أنه متوافق مع microbenchmark بسبب الإرفاق / الفصل.

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 . لديها بناء الجملة بسيطة ومع ذلك هو تقريبا بسرعة مثل أوامر القاعدة R مع مكائدها المعقدة. تعمل هادلي ويكهام الرائعة عادة. إن وجعي الوحيد هو أنه يكسر المصطلحات القياسية R حيث يتم الحصول على تصنيف الكائنات sort(object) ، لكنني أفهم لماذا فعل هادلي ذلك بهذه الطريقة بسبب القضايا التي تمت مناقشتها في السؤال المرتبط أعلاه.

Question

أرغب في فرز 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



هناك الكثير من الإجابات الممتازة هنا ، ولكن 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)

لمشكلة 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






من أجل الاكتمال: يمكنك أيضًا استخدام وظيفة 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



جواب ديرك جيد ، ولكن إذا احتجت إلى استمرار النوع ، فستحتاج إلى تطبيق الترتيب مرة أخرى على اسم إطار البيانات هذا. باستخدام رمز المثال:

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



افترض أن لديك 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 data.frame خلال x تنازلي ، y تصاعدي و تنازلي.




إذا SQL يأتي بشكل طبيعي لك ، يعالج sqldf ORDER BY كما المقصود Codd.






Related