2013-02-10 23 views
28

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

यह this question asked on the r-help mailing list के जवाब में है।

ऐसा करने के तरीके sql का उपयोग करने का here are lots of examples, तो मैं सोच भी यह आर sqldf पैकेज का उपयोग करने पर है कि ज्ञान कन्वर्ट करने के लिए आसान है .. लेकिन वहाँ आर के साथ ऐसा करने के लिए कुछ तरीके हैं, और मैं जाँच करने के लिए चाहता था अगर दूसरों के लिए किया था विचारों।

मुख्य प्रश्न: उदाहरण mtcars डेटा.फ्रेम का उपयोग करके, किसी को किसी निर्दिष्ट श्रेणी के भीतर शीर्ष या नीचे (अधिकतम या न्यूनतम) एन रिकॉर्ड कैसे मिलेगा? शीर्ष या नीचे एन परिणाम, प्रति समूह।

यदि आप आर खोलते हैं और mtcars टाइप करते हैं तो आपको 32 रिकॉर्ड के साथ एक उदाहरण तालिका मिलती है। जब सिलेंडर कॉलम cyl द्वारा समूहित किया गया है - cyl के प्रत्येक विशिष्ट मान के लिए शीर्ष तीन रिकॉर्ड यहां दिए गए हैं। ध्यान दें कि इस मामले में संबंधों को बाहर रखा गया है, लेकिन संबंधों के इलाज के लिए कुछ अलग तरीके दिखाना अच्छा लगेगा।

     mpg cyl disp hp drat wt qsec vs am gear carb ranks 
Toyota Corona  21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1 2.0 
Volvo 142E   21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2 1.0 
Valiant    18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 2.0 
Merc 280   19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 3.0 
Merc 280C   17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4 1.0 
Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4 1.5 
Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4 1.5 
Camaro Z28   13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4 3.0 
+0

मामले में एक समूह में विभिन्न 'k' रिकॉर्ड का चयन करने की जरूरत है, इस सवाल में मदद कर सकते है: http://stackoverflow.com/q/33988831/1840471 –

उत्तर

-1
# start with the mtcars data frame (included with your installation of R) 
mtcars 

# pick your 'group by' variable 
gbv <- 'cyl' 
# IMPORTANT NOTE: you can only include one group by variable here 
# ..if you need more, the `order` function below will need 
# one per inputted parameter: order(x$cyl , x$am) 

# choose whether you want to find the minimum or maximum 
find.maximum <- FALSE 

# create a simple data frame with only two columns 
x <- mtcars 

# order it based on 
x <- x[ order(x[ , gbv ] , decreasing = find.maximum) , ] 

# figure out the ranks of each miles-per-gallon, within cyl columns 
if (find.maximum){ 
    # note the negative sign (which changes the order of mpg) 
    # *and* the `rev` function, which flips the order of the `tapply` result 
    x$ranks <- unlist(rev(tapply(-x$mpg , x[ , gbv ] , rank))) 
} else { 
    x$ranks <- unlist(tapply(x$mpg , x[ , gbv ] , rank)) 
} 
# now just subset it based on the rank column 
result <- x[ x$ranks <= 3 , ] 

# look at your results 
result 

# done! 

# but note only *two* values where cyl == 4 were kept, 
# because there was a tie for third smallest, and the `rank` function gave both '3.5' 
x[ x$ranks == 3.5 , ] 

# ..if you instead wanted to keep all ties, you could change the 
# tie-breaking behavior of the `rank` function. 
# using the `min` *includes* all ties. using `max` would *exclude* all ties 
if (find.maximum){ 
    # note the negative sign (which changes the order of mpg) 
    # *and* the `rev` function, which flips the order of the `tapply` result 
    x$ranks <- unlist(rev(tapply(-x$mpg , x[ , gbv ] , rank , ties.method = 'min'))) 
} else { 
    x$ranks <- unlist(tapply(x$mpg , x[ , gbv ] , rank , ties.method = 'min')) 
} 
# and there are even more options.. 
# see ?rank for more methods 

# now just subset it based on the rank column 
result <- x[ x$ranks <= 3 , ] 

# look at your results 
result 
# and notice *both* cyl == 4 and ranks == 3 were included in your results 
# because of the tie-breaking behavior chosen. 
+0

@ अरुण .. कोई और विकल्प नहीं है? :) अपने भयानक उत्तर के लिए पीएस thanx –

+1

इस तरह के एक साधारण काम के लिए यह जटिल है! – Ista

+0

@ अर्न I नीचे मतदान किया क्योंकि यह बहुत जटिल लगता है, जैसा कि मैंने उपरोक्त मेरी टिप्पणी में शिकायत की थी। शायद मैं अपने ड्राइववे को घूमने के घंटों खर्च करने के बाद थोड़ा सा क्रैकी हूं ... – Ista

31

इस तरह के रूप में यह करता है कुंजी सेट करते समय data.table का उपयोग कर अधिक सरल लगता है।

तो, मैं, प्रकार (आरोही क्रम) में शीर्ष 3 रिकॉर्ड प्राप्त करने के लिए तो,

require(data.table) 
d <- data.table(mtcars, key="cyl") 
d[, head(.SD, 3), by=cyl] 

यह करता थे।

और अगर आप अवरोही क्रम चाहते

d[, tail(.SD, 3), by=cyl] # Thanks @MatthewDowle 

संपादित करें: प्रकार बाहर बांधकरने के लिए mpg स्तंभ का उपयोग: जो कुछ भी (उदाहरण के लिए mpg द्वारा बस प्रकार

d <- data.table(mtcars, key="cyl") 
d.out <- d[, .SD[mpg %in% head(sort(unique(mpg)), 3)], by=cyl] 

#  cyl mpg disp hp drat wt qsec vs am gear carb rank 
# 1: 4 22.8 108.0 93 3.85 2.320 18.61 1 1 4 1 11 
# 2: 4 22.8 140.8 95 3.92 3.150 22.90 1 0 4 2 1 
# 3: 4 21.5 120.1 97 3.70 2.465 20.01 1 0 3 1 8 
# 4: 4 21.4 121.0 109 4.11 2.780 18.60 1 1 4 2 6 
# 5: 6 18.1 225.0 105 2.76 3.460 20.22 1 0 3 1 7 
# 6: 6 19.2 167.6 123 3.92 3.440 18.30 1 0 4 4 1 
# 7: 6 17.8 167.6 123 3.92 3.440 18.90 1 0 4 4 2 
# 8: 8 14.3 360.0 245 3.21 3.570 15.84 0 0 3 4 7 
# 9: 8 10.4 472.0 205 2.93 5.250 17.98 0 0 3 4 14 
# 10: 8 10.4 460.0 215 3.00 5.424 17.82 0 0 3 4 5 
# 11: 8 13.3 350.0 245 3.73 3.840 15.41 0 0 3 4 3 

# and for last N elements, of course it is straightforward 
d.out <- d[, .SD[mpg %in% tail(sort(unique(mpg)), 3)], by=cyl] 
+1

हाय। मैं 'सिर (seq (I.))' के अंदर 'एसडी [...] 'क्या करता है उसका पालन नहीं कर रहा हूं। क्यों नहीं सिर (एसएसडी, 3) '? या 'डी [, एसडी [सिर (आदेश (एमपीजी))], = cyl द्वारा]'। 'd' की कुंजी एक कॉलम (' cyl') है, क्या इसका उद्देश्य कुंजी में 'mpg' शामिल करना था? –

+0

@MatthewDowle, :) इरादा आपका पहला सुझाव था 'सिर (एसएसडी, 3) '। यह 'सिर' सीधा करने के लिए मुझे लगता है! मैं इसे संपादित करूंगा। – Arun

+1

ठीक है, +1। इन दिनों के बारे में टिप्पणी करने के लिए मुझे कुछ भी दुर्लभ लगता है! –

17

, सवाल यह है कि इस पर स्पष्ट नहीं)

mt <- mtcars[order(mtcars$mpg), ] 

फिर प्रत्येक समूह

d <- by(mt, mt["cyl"], head, n=4) 

में शीर्ष एन पंक्तियों प्राप्त करने के लिए समारोह से का उपयोग आप परिणाम चाहते हैं एक data.frame होने के लिए:

Reduce(rbind, d) 

संपादित करें: हैंडलिंग संबंधों अधिक कठिन है, लेकिन यदि सभी संबंध वांछित हैं:

by(mt, mt["cyl"], function(x) x[rank(x$mpg) %in% sort(unique(rank(x$mpg)))[1:4], ]) 

एक और दृष्टिकोण है कुछ अन्य जानकारी के आधार पर संबंध तोड़ने के लिए, उदा।,

mt <- mtcars[order(mtcars$mpg, mtcars$hp), ] 
by(mt, mt["cyl"], head, n=4) 
+0

@ अरुण उम, क्या? एक टाई है जब cyl == 8 भी ... जो data.table समाधान को अनदेखा करता है। इसका उपयोग करके हम दोनों मामलों में दोनों मैचों (mtcars, mtcars ["cyl"], फ़ंक्शन (x) x [रैंक (x $ mpg) Ista

+0

कम करने के लिए +1 (rbind, by (...)) –

+0

सुझाव के लिए निश्चित धन्यवाद। – Ista

4

अगर वहाँ थे mtcars $ एमपीजी के लिए चौथे स्थान पर टाई तो यह सारे रिश्ते लौटना चाहिए:

top_mpg <- mtcars[ mtcars$mpg >= mtcars$mpg[order(mtcars$mpg, decreasing=TRUE)][4] , ] 

> top_mpg 
       mpg cyl disp hp drat wt qsec vs am gear carb 
Fiat 128  32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 
Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2 
Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1 
Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2 

चूंकि 3-4 स्थिति में आप परीक्षण कर सकते हैं पर एक टाई है यह 4 से 3 को बदलकर, और यह अभी भी 4 आइटम लौटाता है। यह लॉजिकल इंडेक्सिंग है और आपको उस क्लॉज को जोड़ने की आवश्यकता हो सकती है जो एनए या रैप को हटा देता है जो() लॉजिकल एक्सप्रेशन के आसपास है। @Ista करने के लिए अपने सुझाव को शामिल

Reduce(rbind, by(mtcars, mtcars$cyl, 
     function(d) d[ d$mpg >= d$mpg[order(d$mpg, decreasing=TRUE)][4] , ])) 
#------------- 
        mpg cyl disp hp drat wt qsec vs am gear carb 
Fiat 128   32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 
Honda Civic  30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2 
Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1 
Lotus Europa  30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2 
Mazda RX4   21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 
Mazda RX4 Wag  21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 
Ferrari Dino  19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6 
Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 
Merc 450SE  16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3 
Merc 450SL  17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3 
Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2 

:

Reduce(rbind, by(mtcars, mtcars$cyl, function(d) d[ d$mpg <= sort(d$mpg)[3] , ])) 
+0

अगर आप हाथ से पहले नहीं जानते हैं तो इसे नहीं करकर इसका मतलब क्या है। यह चौथी सबसे बड़ी कीमत पर या उससे ऊपर एमजीजी मूल्यों के साथ सभी पंक्तियों को वापस कर देगा। फिर यदि आपने लक्ष्य के रूप में तीसरा सबसे बड़ा चुना है, तो आपको अभी भी चार-सिलेंडर कक्षा में 4 आइटम मिलते हैं। मैंने सोचा कि एंथनी के लक्ष्यों में से एक –

+0

जैसा कि मैंने कार्यों को समझ लिया था कि _was_ संबंधों से निपटने में से एक के लिए सही उत्तर है। –

+0

मेरा कोड वह करता है जो आप अनुरोध कर रहे हैं। –

3

आप एक समारोह है कि एक पहलू से डेटाबेस विभाजन, आदेश किसी अन्य के द्वारा लिख ​​सकते हैं यह और अधिक कठिन cyl "द्वारा" यह करने के लिए नहीं है वांछित चर, प्रत्येक कारक (श्रेणी) में इच्छित पंक्तियों की संख्या निकालें और इन्हें डेटाबेस में गठबंधन करें।

top<-function(x, num, c1,c2){ 
sorted<-x[with(x,order(x[,c1],x[,c2],decreasing=T)),] 
splits<-split(sorted,sorted[,c1]) 
df<-lapply(splits,head,num) 
do.call(rbind.data.frame,df)} 

एक्स dataframe है;

num उन पंक्तियों की संख्या है जिन्हें आप देखना चाहते हैं;

c1 चर के स्तंभ संख्या आप से विभाजित करने के लिए चाहते हैं;

c2 चर के स्तंभ संख्या आप द्वारा रैंक या संबंधों को संभालने के लिए चाहते हैं।

mtcars डेटा का उपयोग करना, समारोह अर्क भारी कारों प्रत्येक सिलेंडर कक्षा में

top(mtcars,3,2,6) 
         mpg cyl disp hp drat wt qsec vs am gear carb 
4.Merc 240D   24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 
4.Merc 230   22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 
4.Volvo 142E   21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2 
6.Valiant    18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 
6.Merc 280   19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 
6.Merc 280C   17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4 
8.Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4 
8.Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4 
8.Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4 
(mtcars $ cyl nd स्तंभ है) (mtcars $ wt वें स्तंभ है)

तुम भी आसानी से पूंछ को lapply समारोह में सिर बदलकर या आदेश समारोह में घटते = टी तर्क को हटाने के द्वारा एक कक्षा में सबसे हल्का प्राप्त कर सकते हैं जो इसे अपने डिफ़ॉल्ट, घटने = एफ पर वापस कर देगा।

0

मैं @ इस्ता समाधान पसंद करता हूं, क्योंकि कोई अतिरिक्त पैकेज की आवश्यकता नहीं है और यह आसान है।
data.table समाधान का एक संशोधन भी मेरी समस्या का समाधान करता है, और अधिक सामान्य है। (द्वारा आदेश देने शायद इसलिए है क्योंकि

> require(data.table) 
> dt1 <- data.table(df) 
> dt2 = dt1[order(-efet, G1, G2), head(.SD, 3), by = .(G1, G2)] 
> dt2 
    G1 G2 trees interDepth minObs shrinkage  qx efet prec sens acu 
1: 0 FALSE 2000   2  6  0.010 0.4395953 43.066 0.606 0.575 0.631 
2: 0 FALSE 2000   5  1  0.005 0.4294718 37.554 0.583 0.548 0.607 
3: 0 FALSE 5000   2  6  0.005 0.4395753 36.981 0.575 0.559 0.616 
4: 2 FALSE 5000   3  4  0.001 0.4296346 40.624 0.593 0.570 0.645 
5: 2 FALSE 1000   5  1  0.010 0.4186802 39.915 0.587 0.573 0.647 
6: 2 FALSE 2000   2  4  0.005 0.4390503 39.164 0.582 0.575 0.648 
7: 8 FALSE 2000   4  10  0.001 0.4511349 38.240 0.576 0.576 0.619 
8: 8 FALSE 5000   2  10  0.005 0.4469665 38.064 0.579 0.566 0.611 
9: 8 FALSE 5000   3  6  0.005 0.4426952 37.888 0.588 0.542 0.591 
10: 2 TRUE 5000   3  4  0.001 0.3812878 21.057 0.510 0.479 0.615 
11: 2 TRUE 2000   3  10  0.005 0.3790536 20.127 0.507 0.470 0.608 
12: 2 TRUE 1000   5  4  0.001 0.3690911 18.981 0.500 0.475 0.611 
13: 8 TRUE 5000   6  10  0.010 0.2865042 16.870 0.497 0.435 0.635 
14: 0 TRUE 2000   6  4  0.010 0.3192862 9.779 0.460 0.433 0.621 

किसी कारण से, यह आदेश नहीं करता है जिस तरह से कहा:
मेरे data.frame

> str(df) 
'data.frame': 579 obs. of 11 variables: 
$ trees  : num 2000 5000 1000 2000 1000 1000 2000 5000 5000 1000 ... 
$ interDepth: num 2 3 5 2 3 4 4 2 3 5 ... 
$ minObs : num 6 4 1 4 10 6 10 10 6 6 ... 
$ shrinkage : num 0.01 0.001 0.01 0.005 0.01 0.01 0.001 0.005 0.005 0.001  ... 
$ G1  : num 0 2 2 2 2 2 8 8 8 8 ... 
$ G2  : logi FALSE FALSE FALSE FALSE FALSE FALSE ... 
$ qx  : num 0.44 0.43 0.419 0.439 0.43 ... 
$ efet  : num 43.1 40.6 39.9 39.2 38.6 ... 
$ prec  : num 0.606 0.593 0.587 0.582 0.574 0.578 0.576 0.579 0.588 0.585 ... 
$ sens  : num 0.575 0.57 0.573 0.575 0.587 0.574 0.576 0.566 0.542 0.545 ... 
$ acu  : num 0.631 0.645 0.647 0.648 0.655 0.647 0.619 0.611 0.591 0.594 ... 

data.table समाधान i पर order की जरूरत है काम करने के लिए है समूह)। तो, एक और आदेश किया जाता है।

> dt2[order(G1, G2)] 
    G1 G2 trees interDepth minObs shrinkage  qx efet prec sens acu 
1: 0 FALSE 2000   2  6  0.010 0.4395953 43.066 0.606 0.575 0.631 
2: 0 FALSE 2000   5  1  0.005 0.4294718 37.554 0.583 0.548 0.607 
3: 0 FALSE 5000   2  6  0.005 0.4395753 36.981 0.575 0.559 0.616 
4: 0 TRUE 2000   6  4  0.010 0.3192862 9.779 0.460 0.433 0.621 
5: 2 FALSE 5000   3  4  0.001 0.4296346 40.624 0.593 0.570 0.645 
6: 2 FALSE 1000   5  1  0.010 0.4186802 39.915 0.587 0.573 0.647 
7: 2 FALSE 2000   2  4  0.005 0.4390503 39.164 0.582 0.575 0.648 
8: 2 TRUE 5000   3  4  0.001 0.3812878 21.057 0.510 0.479 0.615 
9: 2 TRUE 2000   3  10  0.005 0.3790536 20.127 0.507 0.470 0.608 
10: 2 TRUE 1000   5  4  0.001 0.3690911 18.981 0.500 0.475 0.611 
11: 8 FALSE 2000   4  10  0.001 0.4511349 38.240 0.576 0.576 0.619 
12: 8 FALSE 5000   2  10  0.005 0.4469665 38.064 0.579 0.566 0.611 
13: 8 FALSE 5000   3  6  0.005 0.4426952 37.888 0.588 0.542 0.591 
14: 8 TRUE 5000   6  10  0.010 0.2865042 16.870 0.497 0.435 0.635 
2

dplyr चाल

mtcars %>% 
arrange(desc(mpg)) %>% 
group_by(cyl) %>% slice(1:2) 


mpg cyl disp hp drat wt qsec vs am gear carb 
    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 
1 33.9  4 71.1 65 4.22 1.835 19.90  1  1  4  1 
2 32.4  4 78.7 66 4.08 2.200 19.47  1  1  4  1 
3 21.4  6 258.0 110 3.08 3.215 19.44  1  0  3  1 
4 21.0  6 160.0 110 3.90 2.620 16.46  0  1  4  4 
5 19.2  8 400.0 175 3.08 3.845 17.05  0  0  3  2 
6 18.7  8 360.0 175 3.15 3.440 17.02  0  0  3  2 
+0

यदि उपयोगकर्ता एसक्यूएल के समान परिणाम में रुचि रखते हैं, तो यह dplyr परिणाम –

+0

हे आज़म जाने का तरीका है, क्या आप अभी भी एक फॉलोअप प्रश्न के लिए सक्रिय हैं? मैं कुछ के लिए इस जवाब का उपयोग कर रहा हूँ – Mark

संबंधित मुद्दे