पांडा समूहों के भीतर समूहों की तरह


166

मैं अपने डेटाफ़्रेम को दो स्तंभों द्वारा समूहित करना चाहता हूं और फिर समूहों के भीतर कुल परिणामों को क्रमबद्ध करता हूं।

In [167]:
df

Out[167]:
count   job source
0   2   sales   A
1   4   sales   B
2   6   sales   C
3   3   sales   D
4   7   sales   E
5   5   market  A
6   3   market  B
7   2   market  C
8   4   market  D
9   1   market  E

In [168]:
df.groupby(['job','source']).agg({'count':sum})

Out[168]:
            count
job     source  
market  A   5
        B   3
        C   2
        D   4
        E   1
sales   A   2
        B   4
        C   6
        D   3
        E   7

अब मैं प्रत्येक समूह के भीतर अवरोही क्रम में गिनती कॉलम को क्रमबद्ध करना चाहूंगा। और फिर केवल शीर्ष तीन पंक्तियों को लें। कुछ पाने के लिए जैसे:

            count
job     source  
market  A   5
        D   4
        B   3
sales   E   7
        C   6
        B   4

जवाबों:


147

आप जो करना चाहते हैं, वह वास्तव में फिर से एक ग्रुपबी (पहले ग्रुपबी के परिणाम पर) है: सॉर्ट करें और प्रति समूह पहले तीन तत्वों को लें।

पहले समूह के परिणाम से शुरू:

In [60]: df_agg = df.groupby(['job','source']).agg({'count':sum})

हम सूचकांक के पहले स्तर के आधार पर समूह बनाते हैं:

In [63]: g = df_agg['count'].groupby(level=0, group_keys=False)

फिर हम प्रत्येक समूह को क्रमबद्ध ('क्रम') करना चाहते हैं और पहले तीन तत्वों को लेते हैं:

In [64]: res = g.apply(lambda x: x.order(ascending=False).head(3))

हालांकि, इसके लिए, ऐसा करने के लिए एक शॉर्टकट फ़ंक्शन है nlargest:

In [65]: g.nlargest(3)
Out[65]:
job     source
market  A         5
        D         4
        B         3
sales   E         7
        C         6
        B         4
dtype: int64

क्या हर उस चीज़ को समेटने का एक तरीका होगा जो प्रति समूह के शीर्ष तीन परिणामों में शामिल नहीं है और उन्हें प्रत्येक नौकरी के लिए "अन्य" नामक एक स्रोत समूह में जोड़ना है?
--गदर

30
ordersort_valuesइसके बजाय उपयोग में
कमी है

महान जवाब के लिए धन्यवाद। एक और कदम के लिए, क्या ग्रुपबी कॉलम में मूल्यों के आधार पर छँटाई क्रम को निर्दिष्ट करने का कोई तरीका होगा? उदाहरण के लिए, मान के the खरीदें ’होने पर आरोही को सॉर्ट करें और यदि मूल्य 'सेल’ है तो अवरोही को सॉर्ट करें।
बोवेन लियू

173

आप इसे केवल एक बार में भी कर सकते हैं, पहले प्रकार को करके और प्रत्येक समूह के पहले 3 को लेने के लिए सिर का उपयोग करके।

In[34]: df.sort_values(['job','count'],ascending=False).groupby('job').head(3)

Out[35]: 
   count     job source
4      7   sales      E
2      6   sales      C
1      4   sales      B
5      5  market      A
8      4  market      D
6      3  market      B

14
क्या groupbyगारंटी देता है कि आदेश संरक्षित है?
टोटो_टिको

52
ऐसा लगता है कि यह करता है; से GroupBy के प्रलेखन : GroupBy प्रत्येक समूह के भीतर पंक्तियों का क्रम बरकरार रखता है
toto_tico

10
toto_tico- यह सही है, हालांकि उस कथन की व्याख्या करने में सावधानी बरतने की जरूरत है। A SINGLE GROUP के साथ पंक्तियों के क्रम को संरक्षित किया जाता है, हालाँकि groupby में एक सॉर्ट = सही कथन होता है, जिसका अर्थ है कि समूह स्वयं कुंजी पर क्रमबद्ध हो सकते हैं। दूसरे शब्दों में यदि मेरे डेटाफ़्रेम में कुंजियाँ हैं (इनपुट पर) 3 2 2 1, .. ऑब्जेक्ट द्वारा समूह 3 समूहों को क्रम 1 2 3 (क्रमबद्ध) में दिखाएगा। समूह क्रम और पंक्ति क्रम संरक्षित है यह सुनिश्चित करने के लिए छाँटे = गलत का उपयोग करें।
user2103050

4
सिर (3) 3 से अधिक परिणाम देता है?
नबिन

27

यहाँ क्रमबद्ध क्रम पर शीर्ष 3 लेने के अन्य उदाहरण हैं, और समूहों के भीतर छंटनी:

In [43]: import pandas as pd                                                                                                                                                       

In [44]:  df = pd.DataFrame({"name":["Foo", "Foo", "Baar", "Foo", "Baar", "Foo", "Baar", "Baar"], "count_1":[5,10,12,15,20,25,30,35], "count_2" :[100,150,100,25,250,300,400,500]})

In [45]: df                                                                                                                                                                        
Out[45]: 
   count_1  count_2  name
0        5      100   Foo
1       10      150   Foo
2       12      100  Baar
3       15       25   Foo
4       20      250  Baar
5       25      300   Foo
6       30      400  Baar
7       35      500  Baar


### Top 3 on sorted order:
In [46]: df.groupby(["name"])["count_1"].nlargest(3)                                                                                                                               
Out[46]: 
name   
Baar  7    35
      6    30
      4    20
Foo   5    25
      3    15
      1    10
dtype: int64


### Sorting within groups based on column "count_1":
In [48]: df.groupby(["name"]).apply(lambda x: x.sort_values(["count_1"], ascending = False)).reset_index(drop=True)
Out[48]: 
   count_1  count_2  name
0       35      500  Baar
1       30      400  Baar
2       20      250  Baar
3       12      100  Baar
4       25      300   Foo
5       15       25   Foo
6       10      150   Foo
7        5      100   Foo

9

इसके बजाय यह प्रयास करें

सरल तरीका 'ग्रुपबी' करना और अवरोही क्रम में छंटनी करना

df.groupby(['companyName'])['overallRating'].sum().sort_values(ascending=False).head(20)

8

यदि आपको कॉलम की राशि की जरूरत नहीं है, तो @ tvashtar के उत्तर का उपयोग करें। यदि आपको योग करने की आवश्यकता है, तो आप @joris के उत्तर का उपयोग कर सकते हैं या यह एक ऐसा है जो इसके समान है।

df.groupby(['job']).apply(lambda x: (x.groupby('source')
                                      .sum()
                                      .sort_values('count', ascending=False))
                                     .head(3))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.