मैं R डेटा फ़्रेम में सभी लेकिन एक विशिष्ट डुप्लिकेट रिकॉर्ड कैसे निकालूं? [बन्द है]


16

मेरे पास एक डेटा फ्रेम है जिसमें कुछ डुप्लिकेट आईडी हैं। मैं अधिकतम मूल्य के साथ केवल पंक्ति रखते हुए डुप्लिकेट आईडी के साथ रिकॉर्ड निकालना चाहता हूं।

तो इस तरह संरचित के लिए (अन्य चर नहीं दिखाए गए):

id var_1
1 2
1 4
2 1
2 3
3 5
4 2

मैं इसे उत्पन्न करना चाहता हूं:

id var_1
1 4
2 3
3 5
4 2

मैं अद्वितीय () और डुप्लिकेट () के बारे में जानता हूं, लेकिन मैं यह पता नहीं लगा सकता कि अधिकतमकरण नियम को कैसे शामिल किया जाए ...


यह वास्तव में स्टैकेओवरफ्लो में होना चाहिए क्योंकि यह विशुद्ध रूप से प्रोग्रामिंग से संबंधित कार्य है और आंकड़ों के साथ बहुत कम है
उत्साही

जवाबों:


24

एक तरीका डेटा को रिवर्स-सॉर्ट करना और duplicatedसभी डुप्लिकेट को छोड़ने के लिए उपयोग करना है। मेरे लिए, यह विधि उन लोगों की तुलना में वैचारिक रूप से सरल है जो उपयोग करते हैं। मुझे लगता है कि यह बहुत तेज होना चाहिए।

# Some data to start with:
z <- data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,5,2))
# id var
#  1   2
#  1   4
#  2   1
#  2   3
#  3   5
#  4   2

# Reverse sort
z <- z[order(z$id, z$var, decreasing=TRUE),]
# id var
#  4   2
#  3   5
#  2   3
#  2   1
#  1   4
#  1   2

# Keep only the first row for each duplicate of z$id; this row will have the
# largest value for z$var
z <- z[!duplicated(z$id),]

# Sort so it looks nice
z <- z[order(z$id, z$var),]
# id var
#  1   4
#  2   3
#  3   5
#  4   2

संपादित करें: मुझे अभी पता चला है कि ऊपर दिए गए रिवर्स सॉर्ट को बिल्कुल भी सॉर्ट करने की आवश्यकता नहीं है id। आप z[order(z$var, decreasing=TRUE),]इसके बजाय बस का उपयोग कर सकते हैं और यह भी काम करेगा।

एक और सोचा ... अगर var कॉलम संख्यात्मक है, तो सॉर्ट करने का एक सरल तरीका है कि idआरोही है, लेकिन varअवरोही है। यह अंत में छंटनी की आवश्यकता को समाप्त करता है (यह मानते हुए कि आप इसे क्रमबद्ध करना चाहते थे)।

z <- data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,5,2))

# Sort: id ascending, var descending
z <- z[order(z$id, -z$var),]

# Remove duplicates
z <- z[!duplicated(z$id),]
# id var
#  1   4
#  2   3
#  3   5
#  4   2

1
यह दृष्टिकोण "स्प्लिट-कंप्यूट-रबिंड" की तुलना में काफी तेज है। इसके अलावा यह एक से अधिक कारकों पर समूह बनाने की अनुमति देता है। एक सी के लिए। 650,000 पंक्ति (8, संकीर्ण, कॉलम) "ऑर्डर-डुप्लिकेटेड" दृष्टिकोण को 55 सेकंड लगे, विभाजन-गणना-आरबीआईंड ... 1h15minute। बेशक जब डुप्लिकेट का चयन या फ़िल्टर करने के अलावा समग्र गणना होती है, तो बाद के दृष्टिकोण या इसी तरह के प्लाई आधारित दृष्टिकोण की आवश्यकता होती है।
mjv

7

आप वास्तव में एक ही आईडी वाले तत्वों से अधिकतम तत्व का चयन करना चाहते हैं। उसके लिए आप ddplyपैकेज plyr से उपयोग कर सकते हैं :

> dt<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,4,2))
> ddply(dt,.(id),summarise,var_1=max(var))
   id var_1
1  1   4
2  2   3
3  3   4
4  4   2

uniqueऔर duplicatedडुप्लिकेट रिकॉर्ड को हटाने के लिए है, आपके मामले में आपके पास केवल डुप्लिकेट आईडी हैं, रिकॉर्ड नहीं।

अद्यतन: यहाँ कोड है जब अतिरिक्त चर रहे हैं:

> dt<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,4,2),bu=rnorm(6))
> ddply(dt,~id,function(d)d[which.max(d$var),])

क्या होगा अगर अन्य चर थे: आप उन्हें साथ कैसे ले जाते हैं?
ऐकियो

हम ऐसे सवालों को आगे नहीं बढ़ाते हैं - बहुत कम लाभ के लिए बहुत अधिक भीड़।

6

आधार-आर समाधान splitइस तरह शामिल होगा :

z<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,4,2))
do.call(rbind,lapply(split(z,z$id),function(chunk) chunk[which.max(chunk$var),]))

splitडेटा फ़्रेम को विखंडू की सूची में विभाजित करता है, जिस पर हम अधिकतम मान के साथ एकल पंक्ति में कटिंग करते हैं और फिर do.call(rbind,...)डेटा पंक्तियों में एकल पंक्तियों की सूची को फिर से घटाते हैं।


1
और हमेशा की तरह यह प्लायर संस्करण की तुलना में लगभग 2x तेज है।

1
@mbq, हां, स्वाभाविक है, लेकिन यदि आप डिबगिंग लागत को शामिल करते हैं, तो सामान्य डेटा सेट के लिए परिणामी गति समान होती है: plyr गति के लिए नहीं, बल्कि स्पष्टता और सुविधा के लिए समर्पित है।
mpiktas

और एवे का उपयोग करना वैसे भी दोगुना है। :)
एडुआर्डो लियोनी

2
@Eduardo aveका एक आवरण है lapply+ split;, कोड (जाँच -

1
@Eduardo हाँ, लेकिन यह सब केवल उपयोग किए गए कारकों के भीतर सदिश छँटाई की एक विचित्र संभावना के कारण काम करता है order; अधिक सामान्य समस्याओं के splitलिए अपरिहार्य है।

5

मैं उपयोग करना पसंद करता हूं ave

dt<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,3,3,4,2))
## use unique if you want to exclude duplicate maxima
unique(subset(dt, var==ave(var, id, FUN=max)))

+1, ave के बारे में नहीं जानता था। यह आर में कब दिखाई दिया?
mpiktas

1

आधार के साथ ऐसा करने का एक और तरीका:

dt<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,4,2))

data.frame(id=sort(unique(dt$var)),max=tapply(dt$var,dt$id,max))
  id max
1  1   4
2  2   3
3  3   4
4  4   2

मैं mpiktas 'plyr समाधान हालांकि पसंद करते हैं।


1

यदि, उदाहरण के रूप में, कॉलम संस्करण पहले से ही आरोही क्रम में है, तो हमें डेटा फ़्रेम को सॉर्ट करने की आवश्यकता नहीं है। हम केवल duplicatedतर्क पास करने वाले फ़ंक्शन का उपयोग करते हैं fromLast = TRUE, इसलिए अंतिम तत्वों को रखते हुए दोहराव को रिवर्स साइड से माना जाता है:

z <- data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,5,2))
z[!duplicated(z$id, fromLast = TRUE), ]

  id var
2  1   4
4  2   3
5  3   5
6  4   2

अन्यथा हम पहले आरोही क्रम में डेटा फ़्रेम को सॉर्ट करते हैं:

z <- z[order(z$id, z$var), ]
z[!duplicated(z$id, fromLast = TRUE), ]

dplyrपैकेज का उपयोग करना :

library(dplyr)
z %>%
  group_by(id) %>%
  summarise(var = max(var))

Source: local data frame [4 x 2]    
  id var
1  1   4
2  2   3
3  3   5
4  4   2
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.