r - रशस - विजय स्तम्भ एंड कीर्ति स्तम्भ
स्तंभ(ओं) द्वारा डेटाफ्रेम को कैसे क्रमबद्ध करें? (10)
तुम्हारी पसंद
-
base
सेorder
-
dplyr
सेdplyr
-
setorder
setorderv
सेsetorder
औरdata.table
-
plyr
सेplyr
-
taRifx
सेtaRifx
-
orderBy
सेdoBy
-
sortData
सेDeducer
अधिकांश समय आपको dplyr
या data.table
समाधानों का उपयोग करना चाहिए, जब तक कि कोई निर्भरता न हो, तब तक base::order
उपयोग करें।
मैंने हाल ही में sort.data.frame को एक सीआरएएन पैकेज में जोड़ा है, जिसने क्लास को संगत बना दिया है जैसा कि यहां चर्चा की गई है: sort.data.frame के लिए जेनेरिक / विधि स्थिरता बनाने का सबसे अच्छा तरीका?
इसलिए, 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
आप उपरोक्त धागे में बताए गए हैडली के रूप में plyr
से arrange()
फ़ंक्शन का भी उपयोग कर सकते हैं:
library(plyr)
arrange(dd,desc(z),b)
बेंचमार्क: ध्यान दें कि मैंने प्रत्येक पैकेज को नए आर सत्र में लोड किया क्योंकि बहुत सारे संघर्ष हुए थे। विशेष रूप से लोड करने से doBy पैकेज को sort
करने का कारण बनता है "निम्न ऑब्जेक्ट्स को 'x (position 17)': b, x, y, z" से मुखौटा किया जाता है, और डेड्यूसर पैकेज लोड करना केविन से sort.data.frame
को ओवरराइट 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)
औसत समय: 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
ध्यान दें कि पैकेज लोड करने के लिए कुछ समय लगता है।
library(Deducer)
microbenchmark(sortData(dd,c("z","b"),increasing= c(FALSE,TRUE)),times=1000)
डेड्यूसर लोड नहीं कर सका। जेजीआर कंसोल की आवश्यकता है।
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))
(रेखाएं निम्न क्वार्टाइल से ऊपरी क्वार्टाइल तक फैली हुई हैं, डॉट औसत है)
इन परिणामों को देखते हुए और सादगी बनाम गति का वजन, मुझे plyr
पैकेज में arrange
करने arrange
मंजूरी देनी होगी। इसका एक सरल वाक्यविन्यास है और फिर भी उतना तेज़ है जितना बेस आर कमांड को उनके घुलनशील मशीनों के साथ करता है। आम तौर पर शानदार हैडली विकम काम करते हैं। इसके साथ मेरा एकमात्र गड़बड़ यह है कि यह मानक आर नामकरण को तोड़ता है जहां सॉर्टिंग ऑब्जेक्ट्स को sort(object)
द्वारा बुलाया जाता है, लेकिन मुझे समझ में आता है कि ऊपर से जुड़े प्रश्न में चर्चा के मुद्दों के कारण हैडली ने ऐसा क्यों किया।
मैं एकाधिक कॉलम द्वारा डेटा.फ्रेम को सॉर्ट करना चाहता हूं। उदाहरण के लिए, नीचे डेटा.फ्रेम के साथ मैं कॉलम 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
Dirk का जवाब अच्छा है, लेकिन अगर आपको जारी रखने के लिए इस तरह की ज़रूरत है तो आप उस डेटा फ्रेम के नाम पर वापस सॉर्ट करना चाहेंगे। उदाहरण कोड का उपयोग करना:
dd <- dd[with(dd, order(-z, b)), ]
आप एड-ऑन टूल्स का उपयोग किए बिना सीधे 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()
के साथ आसान / अधिक प्रत्यक्ष पहुंच के लिए उपयोग करने के बजाय)।
आर पैकेज data.table
एक सीधा सिंटैक्स के साथ डेटा . tables के तेज़ और मेमोरी कुशल ऑर्डरिंग दोनों प्रदान करता है (जिसमें से एक हिस्सा मैट ने अपने जवाब में काफी अच्छी तरह से हाइलाइट किया है)। तब से काफी सुधार हुए हैं और एक नया फ़ंक्शन setorder()
भी है। v1.9.5+
, setorder()
डेटा.फ्रेम के साथ भी काम करता है।
सबसे पहले, हम एक डेटासेट को काफी बड़े बनाएंगे और अन्य उत्तरों से उल्लिखित विभिन्न विधियों को बेंचमार्क करेंगे और फिर डेटाटेबल की विशेषताओं को सूचीबद्ध करेंगे ।
डेटा:
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
.data.table
DT[order(...)]
वाक्यविन्यास अन्य तरीकों (dplyr
) के सबसे तेज़ से ~ 10x तेज था, जबकिdplyr
के समान स्मृति की मात्रा का उपभोग करतेdplyr
।data.table
.data.table
काsetorder()
अन्य तरीकों (dplyr
) की तुलना में ~ 14x तेज था, जबकि केवल 0.4 जीबी अतिरिक्त मेमोरी ले रहा था।dat
अब हमें आवश्यक क्रम में है (क्योंकि इसे संदर्भ द्वारा अपडेट किया गया है)।
डेटाटेबल विशेषताएं:
गति:
डेटाटेबल का ऑर्डरिंग बेहद तेज़ है क्योंकि यह रेडिक्स ऑर्डरिंग लागू करता है।
सिंटैक्स
DT[order(...)]
डेटाटेबल के तेज़ ऑर्डरिंग का उपयोग करने के लिए आंतरिक रूप से अनुकूलित किया गया है। आप परिचित बेस आर सिंटैक्स का उपयोग जारी रख सकते हैं लेकिन प्रक्रिया को तेज कर सकते हैं (और कम मेमोरी का उपयोग करें)।
याद:
अधिकांश बार, हमें रीडरिंग के बाद मूल डेटा.फ्रेम या डेटाटेबल की आवश्यकता नहीं होती है। यही है, हम आमतौर पर परिणाम को उसी ऑब्जेक्ट पर असाइन करते हैं, उदाहरण के लिए:
DF <- DF[order(...)]
मुद्दा यह है कि मूल वस्तु की स्मृति को कम से कम दो बार (2x) की आवश्यकता होती है। स्मृति कुशल होने के लिए , डेटा.table इसलिए फ़ंक्शन
setorder()
भी प्रदान करता है।setorder()
किसी भी अतिरिक्त प्रतियों के बिनाby reference
( जगह में )by reference
data.tablesby reference
। यह केवल एक कॉलम के आकार के बराबर अतिरिक्त मेमोरी का उपयोग करता है।
अन्य सुविधाओं:
यह
integer
,logical
,numeric
,character
और यहां तक किbit64::integer64
प्रकार का समर्थन करता है।ध्यान दें कि
factor
,Date
,POSIXct
आदि .. कक्षाएं अतिरिक्त गुणों के साथ सभीinteger
/numeric
प्रकार हैं और इसलिए भी समर्थित हैं।बेस आर में, हम उस कॉलम द्वारा घटते क्रम में सॉर्ट करने के लिए एक वर्ण वेक्टर पर उपयोग नहीं कर सकते हैं। इसके बजाय हमें
-xtfrm(.)
का उपयोग-xtfrm(.)
।हालांकि, डेटाटेबल में , हम बस कर सकते हैं, उदाहरण के लिए,
dat[order(-x)]
setorder(dat, -x)
dat[order(-x)]
याsetorder(dat, -x)
।
प्रोग्रामेटिक रूप से सॉर्ट करने के तरीके के लिए ओपी में एक टिप्पणी के जवाब में:
dplyr
और data.table
का उपयोग करना
library(dplyr)
library(data.table)
dplyr
बस arrange_
उपयोग 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
बहुत पहले के यांत्रिक कार्ड सॉर्टर्स की तरह, पहले कम से कम महत्वपूर्ण कुंजी द्वारा क्रमबद्ध करें, फिर अगला सबसे महत्वपूर्ण, आदि। कोई पुस्तकालय आवश्यक नहीं है, किसी भी कुंजी के साथ काम करता है और आरोही और अवरोही कुंजी के किसी भी संयोजन के साथ काम करता है।
dd <- dd[order(dd$b, decreasing = FALSE),]
अब हम सबसे महत्वपूर्ण कुंजी करने के लिए तैयार हैं। क्रम स्थिर है, और सबसे महत्वपूर्ण कुंजी में किसी भी संबंध को पहले ही हल कर लिया गया है।
dd <- dd[order(dd$z, decreasing = 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
द्वारा सॉर्ट कर रहा है, न कि data frame data
में Age
नामक कॉलम द्वारा।
इसे देखने के लिए थोड़ा अलग कॉलम नामों के साथ read.table
का उपयोग 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
my.data
में कॉलम age
पर my.data
।
databyage = my.data[order(my.data$age),]
मैंने सोचा कि यह पोस्टिंग के लायक था यह देखते हुए कि मैं इतनी देर तक इस उदाहरण से कितना उलझन में था। यदि यह पोस्ट थ्रेड के लिए उपयुक्त समझा नहीं गया है तो मैं इसे हटा सकता हूं।
संपादित करें: 13 मई, 2014
कॉलम नाम निर्दिष्ट किए बिना प्रत्येक कॉलम द्वारा डेटा फ्रेम को सॉर्ट करने का एक सामान्य तरीका नीचे दिया गया है। नीचे दिया गया कोड दिखाता है कि बाएं से दाएं या दाएं से बाएं कैसे क्रमबद्ध करें। यह काम करता है अगर हर कॉलम संख्यात्मक है। मैंने जोड़े गए वर्ण स्तंभ के साथ प्रयास नहीं किया है।
मुझे एक महीने या दो बार एक अलग साइट पर एक पुरानी पोस्ट में do.call
कोड मिला, लेकिन केवल व्यापक और कठिन खोज के बाद। मुझे यकीन नहीं है कि मैं अब उस पोस्ट को स्थानांतरित कर सकता हूं। R
में data.frame
ऑर्डर करने के लिए वर्तमान धागा पहला हिट है। इसलिए, मैंने सोचा कि उस मूल 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
यदि एसक्यूएल आपके लिए स्वाभाविक रूप से आता है, तो एसकल्डएफ ऑर्डर को कोडड के रूप में संभालता है।
या आप पैकेज doBy का उपयोग कर सकते हैं
library(doBy)
dd <- orderBy(~-z+b, data=dd)
वैकल्पिक रूप से, पैकेज डेड्यूसर का उपयोग कर
library(Deducer)
dd<- sortData(dd,c("z","b"),increasing= c(FALSE,TRUE))