एकाधिक कॉलम द्वारा डेटाफ्रेम कैसे सॉर्ट करें


1316

मैं कई कॉलमों द्वारा डेटा.फ्रेम सॉर्ट करना चाहता हूं। उदाहरण के लिए, नीचे दिए गए 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

जवाबों:


1624

आप 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()आसान / अधिक प्रत्यक्ष पहुंच के लिए)।


@ डर्क एडल्डबुलेट मैट्रिस के लिए एक समान सरल विधि है?
जोता

14
उसी तरह काम करना चाहिए, लेकिन आप उपयोग नहीं कर सकते withM <- 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"]),]इसे दो कॉलम पर ऑर्डर करने के लिए उपयोग करें।
डिर्क एडल्डबुलेटेल

4
काफी आसान है: dd[ order(-dd[,4], dd[,1]), ]लेकिन withनाम-आधारित सबसेट का उपयोग नहीं कर सकते ।
डिर्क एडल्डबुलेटेल

18
दूसरे उदाहरण को चलाते समय "अमान्य ऑपरेटर के पास अमान्य तर्क" त्रुटि है।
नेलगंज

21
"अमान्य तर्क एकात्मक ऑपरेटर के लिए" त्रुटि तब होती है जब आप वर्ण स्तंभ के साथ ऋण का उपयोग करते हैं। xtfrmउदाहरण के लिए, कॉलम को लपेटकर इसे हल करें dd[ order(-xtfrm(dd[,4]), dd[,1]), ]
रिची कॉटन

476

तुम्हारी पसंद

  • order से base
  • arrange से dplyr
  • setorderऔर setordervसेdata.table
  • arrange से plyr
  • sort से taRifx
  • orderBy से doBy
  • sortData से Deducer

ज्यादातर समय आपको dplyrया data.tableसमाधान का उपयोग करना चाहिए , जब तक कि कोई निर्भरता महत्वपूर्ण न हो, जिस स्थिति में उपयोग करें base::order


मैंने हाल ही में एक CRAN पैकेज में Sort.data.frame जोड़ा है, जिससे यहां चर्चा के रूप में वर्ग संगत हो जाता है: 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


आप arrange()फ़ंक्शन का उपयोग भी कर सकते हैं जैसा plyrकि हेडली ने उपरोक्त सूत्र में बताया है:

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

बेंचमार्क: ध्यान दें कि मैंने प्रत्येक पैकेज को नए आर सत्र में लोड किया था क्योंकि बहुत सारे संघर्ष थे। विशेष रूप से doBy पैकेज को लोड करने के कारण sort"x (स्थिति 17): b, x, y, z" से निम्नलिखित ऑब्जेक्ट (ओं) को वापस लाया जाता है और sort.data.frameकेविन राइट या taififx पैकेज से Deducer पैकेज को अधिलेखित किया जाता है।

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

माध्य समय: ian६२

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)

अटैच / डिटैच होने के कारण माइक्रोबेनमार्क के साथ संगत प्रतीत नहीं होता है।


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

microbenchmark प्लॉट

(लाइनें निम्न चतुर्थक से ऊपरी चतुर्थक तक विस्तृत होती हैं, डॉट माध्यिका है)


इन परिणामों को देखते हुए और सरलता बनाम वजन की गति को देखते हुए, मुझे पैकेज arrangeमें जानकारीplyr देनी होगी । इसका एक सरल वाक्यविन्यास है और फिर भी लगभग उतना ही तेज है जितना कि आर आर उनके दृढ़ तंत्र के साथ कमांड करता है। आमतौर पर शानदार हैडली विकम काम करते हैं। इसके साथ मेरी एकमात्र पकड़ यह है कि यह मानक आर नामकरण को तोड़ता है जहां सॉर्टिंग ऑब्जेक्ट्स को कॉल किया जाता है sort(object), लेकिन मुझे समझ में आता है कि हेडली ने ऊपर दिए गए प्रश्न में चर्चा के मुद्दों के कारण ऐसा क्यों किया।


3
ऊपर ggplot2 माइक्रोबेनमार्क फ़ंक्शन अब उपलब्ध है taRifx::autoplot.microbenchmark
अरी बी। फ्रीडमैन

@ AriB.Friedman y अक्ष अंतराल / पैमाने क्या हैं?
naught101

@ naught101 y अक्ष 0. पर शुरू होता है। स्केल माइक्रोसेकंड होना चाहिए।
अरी बी। फ्रीडमैन

2
@ देखें bनमूना में कैसे सॉर्ट किया गया है। डिफॉल्ट आरोही द्वारा सॉर्ट किया जाता है, इसलिए आप इसे केवल लपेटें नहीं desc। दोनों में आरोही arrange(dd,z,b):। दोनों में उतरते हुए arrange(dd,desc(z),desc(b)):।
अरी बी। फ्रीडमैन

2
प्रति के रूप में ?arrange: "# नोट: प्लाई कार्यों पंक्ति को सुरक्षित नहीं है। नाम"। arrange()यदि कोई रखना चाहता है तो यह उत्कृष्ट कार्य को अपनाता है row.names
लैंडरोनी

148

डिर्क का जवाब बहुत अच्छा है। यह 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)]

यह बहुत छोटा अंतर है, लेकिन यह सिर्फ एक दिन आपकी गर्दन को बचा सकता है। इस प्रश्न के विभिन्न उत्तरों को तौलते समय, निर्णय लेने में आपके एक मापदंड के रूप में चर नामों की पुनरावृत्ति की गणना पर विचार करें। कुछ जवाबों में कुछ दोहराए गए हैं, दूसरों के पास कोई नहीं है।


9
+1 यह एक शानदार बिंदु है, और आर के सिंटैक्स के विस्तार पर मिलता है जिसने मुझे अक्सर परेशान किया है। मैं कभी-कभी subset()केवल एक कॉल के भीतर एक ही वस्तु को बार-बार संदर्भित करने से बचने के लिए उपयोग करता हूं ।
जोश ओ'ब्रायन

2
@ n-0101 क्या डेटा.टेबल एफएक्यू 1.9 का जवाब देता है?
मैट डोले

5
मुझे लगता है कि आप नए setorderफ़ंक्शन को भी यहां जोड़ सकते हैं , क्योंकि यह धागा वह है जहां हम सभी orderप्रकार के ड्यूप्स भेजते हैं ।
डेविड अर्नबर्ग

125

यहाँ बहुत सारे उत्कृष्ट उत्तर हैं, लेकिन 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

2
स्वीकृत कॉलम तब काम नहीं करता जब मेरे कॉलम या टाइप फैक्टर (या ऐसा कुछ) हो और मैं आरोही फैशन में पूर्णांक कॉलम के बाद इस कारक कॉलम के लिए अवरोही फैशन में सॉर्ट करना चाहता हूं। लेकिन यह ठीक काम करता है! धन्यवाद!
साहिल गोधने

10
"केवल" ही क्यों? मुझे लगता है कि data.table का dd[order(-z, b)]उपयोग करना और याद रखना बहुत आसान है।
मैट डोले

2
सहमत, उन दो तरीकों के बीच बहुत कुछ नहीं है, और कई अन्य तरीकों से भी बहुत data.tableबड़ा योगदान है R। मुझे लगता है, मेरे लिए यह हो सकता है कि इस उदाहरण में एक कम सेट ब्रैकेट्स (या एक कम प्रकार के ब्रैकेट्स) होने से संज्ञानात्मक भार केवल बमुश्किल समझी जाने वाली राशि से कम हो जाता है।
बेन

7
मेरे लिए यह इस तथ्य पर उतरता है कि arrange()पूरी तरह से घोषणात्मक है, dd[order(-z, b)]नहीं है।
मुल्लेफा

83

R पैकेज एक सीधा वाक्यविन्यास (मैट का एक हिस्सा जो उसके उत्तर में काफी अच्छी तरह से उजागर किया गया है ) के साथ data.tables के तेज और मेमोरी कुशल आदेश data.tableदोनों प्रदान करता है । तब से काफी सुधार हुआ है और एक नया कार्य भी हुआ है । से , डेटा.फ्रेम के साथ भी काम करता है ।setorder()v1.9.5+setorder()

सबसे पहले, हम एक डेटासेट बड़ा बनाएँगे और अन्य उत्तरों से उल्लिखित विभिन्न विधियों को बेंचमार्क करेंगे और फिर 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.4GB अतिरिक्त स्मृतिdatअब उस क्रम में है जिसकी हमें आवश्यकता है (जैसा कि इसे संदर्भ द्वारा अद्यतन किया गया है)।

डेटा सुविधाएँ:

गति:

  • data.table का ऑर्डर बेहद तेज है क्योंकि यह रेडिक्स ऑर्डर को लागू करता है ।

  • सिंटैक्स DT[order(...)]को डेटा के उपयोग के लिए आंतरिक रूप से अनुकूलित किया जाता है। आप परिचित आधार आर सिंटैक्स का उपयोग कर सकते हैं, लेकिन प्रक्रिया को गति दें (और कम मेमोरी का उपयोग करें)।

याद:

  • अधिकांश समय, हम मूल की आवश्यकता नहीं है data.frame या data.table उनका क्रम बदलने के बाद। अर्थात्, हम आम तौर पर परिणाम को उसी वस्तु पर वापस नियत करते हैं, उदाहरण के लिए:

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

    मुद्दा यह है कि इसके लिए कम से कम दो बार (2x) मूल वस्तु की मेमोरी की आवश्यकता होती है। होना करने के लिए स्मृति कुशल , data.table इसलिए भी एक समारोह प्रदान करता है setorder()

    setorder()किसी भी अतिरिक्त प्रतियां बनाने के बिना data.tables by reference ( इन-प्लेस ) को पुन: व्यवस्थित करता है । यह केवल एक कॉलम के आकार के बराबर अतिरिक्त मेमोरी का उपयोग करता है।

अन्य सुविधाओं:

  1. यह समर्थन करता है integer, logical, numeric, characterऔर यहां तक कि bit64::integer64प्रकार के।

    ध्यान दें कि factor, Date, POSIXctआदि .. वर्गों सब कर रहे हैं integer/ numericप्रकार अतिरिक्त विशेषताओं के साथ नीचे और इसलिए अच्छी तरह से समर्थित हैं।

  2. बेस आर में, हम -घटते क्रम में उस कॉलम द्वारा छाँटने के लिए एक चरित्र वेक्टर पर उपयोग नहीं कर सकते हैं । इसके बजाय हमें उपयोग करना होगा -xtfrm(.)

    हालाँकि, data.table में , हम सिर्फ उदाहरण के लिए, dat[order(-x)]या कर सकते हैं setorder(dat, -x)


Data.table के बारे में बहुत ही शिक्षाप्रद उत्तर के लिए धन्यवाद। हालांकि, मुझे समझ नहीं आ रहा है कि "पीक मेमोरी" क्या है और आपने इसकी गणना कैसे की। क्या आप कृपया समझा सकते हैं? धन्यवाद !
जूलियन नवरे

मैंने इंस्ट्रूमेंट्स का उपयोग किया -> आवंटन और "सभी ढेर और आवंटन वीएम" आकार की सूचना दी।
अरुण

2
@ आपकी टिप्पणी में इंस्ट्रूमेंट्स लिंक मृत है। एक अद्यतन पोस्ट करने के लिए देखभाल?
माइकल किरिको 15

@MichaelChirico यहां Apple द्वारा बनाए गए इंस्ट्रूमेंट्स के बारे में जानकारी के लिए एक लिंक है: developer.apple.com/library/content/documentation/…
n1k31t4

73

साथ इस (बहुत उपयोगी) समारोह केविन राइट द्वारा , आर विकी के सुझाव दिए गए अनुभाग में पोस्ट, यह आसानी से हासिल की है।

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

2
इस फ़ंक्शन में उपयोग किए गए एल्गोरिदम के बेंचमार्किंग के लिए मेरा जवाब देखें।
अरी बी। फ्रीडमैन


39

मान लीजिए कि आपके पास एक है 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अवरोही द्वारा क्रमबद्ध ।


32

यदि SQL स्वाभाविक रूप से आपके पास आता है, तो sqldfपैकेज का ORDER BYकोडक के रूप में इरादा होता है।


7
एमजेएम, इस पैकेज को इंगित करने के लिए धन्यवाद। यह अविश्वसनीय रूप से लचीला है और क्योंकि मेरा आधा काम पहले ही sql डेटाबेस से खींचकर किया जा चुका है, यह सहज वाक्य रचना की तुलना में R के बहुत कम सीखने से ज्यादा आसान है।
ब्रैंडन बर्टेल्सन

31

वैकल्पिक रूप से, पैकेज Deducer का उपयोग कर

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

19

ओपी में एक टिप्पणी के जवाब में क्रमबद्ध रूप से क्रमबद्ध कैसे करें:

का उपयोग कर 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

18

मैंने 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),]

मैंने सोचा था कि यह पोस्ट करने के लायक था कि मैं इस उदाहरण से बहुत लंबे समय तक भ्रमित था। यदि यह पद उस थ्रेड के लिए उपयुक्त नहीं है जिसे मैं हटा सकता हूं।

EDIT: 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

4
यदि आप अपने डेटा को डेटा में संग्रहीत करते हैं तो सिंटैक्स काम करता है। डेटा के बजाय require(data.table); my.dt <- data.table(my.data); my.dt[order(age)]
फ्रैंक

मुझे नहीं लगता कि downvote यहाँ आवश्यक है, लेकिन न तो मैं इस के लिए बहुत कुछ कहते हैं लगता है कि सवाल हाथ में, विशेष रूप से उत्तर, जिनमें से कुछ पहले से ही साथ आवश्यकता पर कब्जा की मौजूदा सेट पर विचार data.frameया तो उपयोग करने के लिए रों withया $
a5C1D2H2I1M1N2O1R2T1

1
इसके लिए upvote do.callएक बहुरंगी डेटा फ्रेम को छाँटने का छोटा काम करता है। बस do.call(sort, mydf.obj)और एक सुंदर झरना प्रकार होगा।
एडमो

17

डिर्क का उत्तर अच्छा है, लेकिन यदि आपको उस तरह की जरूरत है, तो आप उस डेटा फ्रेम के नाम पर वापस छांटना चाहते हैं। उदाहरण कोड का उपयोग करना:

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

13

Dplyer में व्यवस्था () मेरा पसंदीदा विकल्प है। पाइप ऑपरेटर का उपयोग करें और कम से कम महत्वपूर्ण से सबसे महत्वपूर्ण पहलू पर जाएं

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

7

पूर्णता के लिए, चूंकि स्तंभ संख्याओं को छाँटने के बारे में बहुत कुछ नहीं कहा गया है ... यह निश्चित रूप से तर्क दिया जा सकता है कि यह अक्सर वांछनीय नहीं है (क्योंकि स्तंभों का क्रम बदल सकता है, त्रुटियों के लिए मार्ग प्रशस्त करता है), लेकिन कुछ विशिष्ट स्थितियों में (जब उदाहरण के लिए आपको किसी त्वरित कार्य की आवश्यकता होती है और कॉलम बदलने के आदेशों का ऐसा कोई जोखिम नहीं होता है), तो ऐसा करना सबसे समझदारी वाली बात हो सकती है, खासकर जब बड़ी संख्या में स्तंभों के साथ काम करना।

उस मामले में, do.call()बचाव के लिए आता है:

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

पूर्णता के लिए: आप पैकेज 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

4
जब आपकी विधि सबसे धीमी है, तो एक प्रदर्शन तुलना जोड़ने के लिए अजीब ... वैसे भी एक 4-पंक्ति पर एक बेंचमार्क का उपयोग करने का संदिग्ध संदिग्धdata.frame
माइकल किरकिरा

5

ठीक पहले की तरह यांत्रिक कार्ड सॉर्टर्स, पहले कम से कम महत्वपूर्ण कुंजी द्वारा क्रमबद्ध करें, फिर अगले सबसे महत्वपूर्ण, आदि। किसी भी पुस्तकालय की आवश्यकता नहीं है, किसी भी संख्या में कुंजी और आरोही और अवरोही कुंजियों के किसी भी संयोजन के साथ काम करता है।

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

अब हम सबसे महत्वपूर्ण कुंजी करने के लिए तैयार हैं। सॉर्ट स्थिर है, और सबसे महत्वपूर्ण कुंजी में किसी भी संबंध को पहले ही हल किया जा चुका है।

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

यह सबसे तेज़ नहीं हो सकता है, लेकिन यह निश्चित रूप से सरल और विश्वसनीय है



4

मैं उपरोक्त समाधानों से जूझ रहा था जब मैं एन कॉलम के लिए अपनी ऑर्डरिंग प्रक्रिया को स्वचालित करना चाहता था, जिनके कॉलम के नाम हर बार अलग हो सकते हैं। मुझे psychपैकेज से एक सुपर सहायक कार्य सीधे तरीके से करने के लिए मिला:

dfOrder(myDf, columnIndices)

जहाँ columnIndicesआप उन्हें सॉर्ट करना चाहते हैं, उस क्रम में एक या अधिक कॉलम के सूचक हैं। अधिक जानकारी यहाँ:

dfOrder 'psych' पैकेज से कार्य करता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.