पंडों को प्रत्येक समूह के भीतर सर्वोच्च एन रिकॉर्ड प्राप्त होते हैं


162

मान लीजिए कि मेरे पास इस तरह से पंडों का डेटाफ़्रेम है:

>>> df = pd.DataFrame({'id':[1,1,1,2,2,2,2,3,4],'value':[1,2,3,1,2,3,4,1,1]})
>>> df
   id  value
0   1      1
1   1      2
2   1      3
3   2      1
4   2      2
5   2      3
6   2      4
7   3      1
8   4      1

मैं प्रत्येक आईडी के लिए शीर्ष 2 रिकॉर्ड के साथ एक नया डेटाफ़्रेम प्राप्त करना चाहता हूं:

   id  value
0   1      1
1   1      2
3   2      1
4   2      2
7   3      1
8   4      1

मैं इसे समूह के बाद समूह में रिकॉर्ड संख्या के साथ कर सकता हूं:

>>> dfN = df.groupby('id').apply(lambda x:x['value'].reset_index()).reset_index()
>>> dfN
   id  level_1  index  value
0   1        0      0      1
1   1        1      1      2
2   1        2      2      3
3   2        0      3      1
4   2        1      4      2
5   2        2      5      3
6   2        3      6      4
7   3        0      7      1
8   4        0      8      1
>>> dfN[dfN['level_1'] <= 1][['id', 'value']]
   id  value
0   1      1
1   1      2
3   2      1
4   2      2
7   3      1
8   4      1

लेकिन क्या ऐसा करने के लिए अधिक प्रभावी / सुरुचिपूर्ण दृष्टिकोण है? और प्रत्येक समूह (SQL विंडो फ़ंक्शन row_number () ) के भीतर संख्या रिकॉर्ड के लिए भी अधिक सुरुचिपूर्ण दृष्टिकोण है ।



1
"टॉप-एन" का मतलब यह नहीं है "एन टॉपेस्ट / फर्स्ट / हेड रो", जैसे आप खोज रहे हैं! इसका अर्थ है "सबसे बड़े मूल्यों के साथ n पंक्तियाँ"।
एसएमसीआई

जवाबों:


183

क्या आप ने कोशिश की df.groupby('id').head(2)

ऊपुत उत्पन्न:

>>> df.groupby('id').head(2)
       id  value
id             
1  0   1      1
   1   1      2 
2  3   2      1
   4   2      2
3  7   3      1
4  8   4      1

(ध्यान रखें कि आपको अपने डेटा के आधार पर ऑर्डर करने / क्रमबद्ध करने की आवश्यकता हो सकती है)

संपादित करें: जैसा कि प्रश्नकर्ता ने उल्लेख किया है, df.groupby('id').head(2).reset_index(drop=True)मल्टीइन्डेक्स को हटाने और परिणामों को समतल करने के लिए उपयोग करें।

>>> df.groupby('id').head(2).reset_index(drop=True)
    id  value
0   1      1
1   1      2
2   2      1
3   2      2
4   3      1
5   4      1

1
हाँ, मुझे लगता है कि यह है। इसे किसी तरह अनदेखा कर दिया। क्या आप समूह के भीतर संख्या रिकॉर्ड करने का अच्छा तरीका जानते हैं?
रोमन पाकर

4
आउटपुट प्राप्त करने के लिए मुझे आवश्यकता है, मैंने भी जोड़ा.reset_index(drop=True)
रोमन पाकर

1
github.com/pydata/pandas/pull/5510 अभी मिला दिया गया था; 0.13 में होगा, इसे करने के लिए नई विधि cumcount(प्रत्येक समूह में रिकॉर्ड संख्या)
जेफ

1
@ अच्छी खबर। मेरी इच्छा है कि मेरे पास पंडों में योगदान करने के लिए अधिक समय हो :(
रोमन पाकर

3
@ उत्तर को और अधिक पूर्ण बनाने के लिए, यदि आप प्रति 2 छोटे मान चाहते हैं idतो करें df.sort_values(['id', 'value'], axis=0).groupby('id').head(2)। एक और उदाहरण, प्रति सबसे बड़ा मूल्य idदिया गया है df.sort_values(['id', 'value'], axis=0).groupby('id').tail(1)
Elmex80s

131

0.14.1 के बाद से , अब आप कर सकते हैं nlargestऔर nsmallestएक groupbyवस्तु पर:

In [23]: df.groupby('id')['value'].nlargest(2)
Out[23]: 
id   
1   2    3
    1    2
2   6    4
    5    3
3   7    1
4   8    1
dtype: int64

वहाँ एक मामूली weirdness कि तुम वहाँ में मूल सूचकांक के रूप में अच्छी तरह से मिलता है, लेकिन यह क्या अपने मूल सूचकांक के आधार पर वास्तव में उपयोगी हो सकता है था

अगर आपको इसमें कोई दिलचस्पी नहीं है, तो आप .reset_index(level=1, drop=True)इससे पूरी तरह छुटकारा पा सकते हैं ।

(नोट: 0.17.1 से आप एक DataFrameGroupBy पर भी यह करने के लिए सक्षम हो जाएगा, लेकिन अब के लिए यह केवल के साथ काम करता Seriesहै और SeriesGroupBy।)


पाने का कोई रास्ता है unique_limit(n)? जैसे मुझे पहला n अनोखा मान चाहिए? अगर मैं इसके लिए पूछूं nlargestतो पूरे df को
छाँट दूंगा

2
यह उन मामलों के लिए काम नहीं करता है जब आप समूह पर एक समग्र कार्य करते हैं? उदाहरण के लिए, df.groupby([pd.Grouper(freq='M'), 'A'])['B'].count().nlargest(5, 'B') यह पूरी श्रृंखला में समग्र शीर्ष 5 को लौटाता है, प्रत्येक समूह द्वारा नहीं
भू

यह कथन कि अब DataFrameGroupBys पर भी संभव है , गलत प्रतीत होता है, जुड़ा हुआ पुल अनुरोध केवल nlargestसाधारण DataFrames में जोड़ने के लिए प्रकट होता है । जो दुर्भाग्यपूर्ण है, क्योंकि क्या होगा यदि आप एक से अधिक कॉलम का चयन करना चाहते हैं?
ऑलेंज

7

कभी-कभी पूरे डेटा को छाँटने में बहुत समय लगता है। हम पहले समूह बना सकते हैं और प्रत्येक समूह के लिए शीर्ष कर सकते हैं:

g = df.groupby(['id']).apply(lambda x: x.nlargest(topk,['value'])).reset_index(drop=True)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.