उन रो (ओं) को प्राप्त करें जिनकी ग्रुपबी का उपयोग करने वाले समूहों में अधिकतम गिनती है


244

मैं पंडों डेटाफ़्रेम की सभी पंक्तियों को कैसे ढूँढ सकता हूँ जिनके countकॉलम के लिए समूहीकरण के बाद कॉलम के लिए अधिकतम मूल्य है ['Sp','Mt']?

उदाहरण 1: निम्न डेटा फ़्रेम, जिसे मैं समूह द्वारा ['Sp','Mt']:

   Sp   Mt Value   count
0  MM1  S1   a      **3**
1  MM1  S1   n      2
2  MM1  S3   cb     5
3  MM2  S3   mk      **8**
4  MM2  S4   bg     **10**
5  MM2  S4   dgd      1
6  MM4  S2  rd     2
7  MM4  S2   cb      2
8  MM4  S2   uyi      **7**

अपेक्षित आउटपुट: परिणाम पंक्तियों को प्राप्त करें जिनकी संख्या समूहों के बीच अधिकतम है, जैसे:

0  MM1  S1   a      **3**
1 3  MM2  S3   mk      **8**
4  MM2  S4   bg     **10** 
8  MM4  S2   uyi      **7**

उदाहरण 2: यह डेटाफ्रेम, जिसे मैं समूह द्वारा ['Sp','Mt']:

   Sp   Mt   Value  count
4  MM2  S4   bg     10
5  MM2  S4   dgd    1
6  MM4  S2   rd     2
7  MM4  S2   cb     8
8  MM4  S2   uyi    8

उपर्युक्त उदाहरण के लिए, मैं उन सभी पंक्तियों को प्राप्त करना चाहता हूँ जहाँ countप्रत्येक समूह में अधिकतम के बराबर हो, जैसे:

MM2  S4   bg     10
MM4  S2   cb     8
MM4  S2   uyi    8

आपका डेटा फ़्रेम किस प्रारूप में है?
डेविड रॉबिन्सन

2
मुझे नहीं मिला। वास्तव में एक समूह क्या है? परिणाम में दूसरी पंक्ति क्यों शुरू होती है 1 3?
जो तो

stackoverflow.com/questions/18879782/… उपयोगी हो सकता है
J_Arthur

1
यह उत्तर सबसे तेज़ समाधान है जो मुझे मिल सकता है: stackoverflow.com/a/21007047/778533
tommy.carstensen

इस प्रश्न के समान, क्या कोई इसका उत्तर दे सकता है: stackoverflow.com/questions/62069465/… धन्यवाद।
ds_Abc

जवाबों:


325
In [1]: df
Out[1]:
    Sp  Mt Value  count
0  MM1  S1     a      3
1  MM1  S1     n      2
2  MM1  S3    cb      5
3  MM2  S3    mk      8
4  MM2  S4    bg     10
5  MM2  S4   dgd      1
6  MM4  S2    rd      2
7  MM4  S2    cb      2
8  MM4  S2   uyi      7

In [2]: df.groupby(['Mt'], sort=False)['count'].max()
Out[2]:
Mt
S1     3
S3     8
S4    10
S2     7
Name: count

मूल DF के संकेत प्राप्त करने के लिए आप यह कर सकते हैं:

In [3]: idx = df.groupby(['Mt'])['count'].transform(max) == df['count']

In [4]: df[idx]
Out[4]:
    Sp  Mt Value  count
0  MM1  S1     a      3
3  MM2  S3    mk      8
4  MM2  S4    bg     10
8  MM4  S2   uyi      7

ध्यान दें कि यदि आपके पास प्रति समूह में कई अधिकतम मूल्य हैं, तो सभी वापस कर दिए जाएंगे।

अपडेट करें

ओला के इस अवसर पर ओपी अनुरोध कर रहे हैं:

In [5]: df['count_max'] = df.groupby(['Mt'])['count'].transform(max)

In [6]: df
Out[6]:
    Sp  Mt Value  count  count_max
0  MM1  S1     a      3          3
1  MM1  S1     n      2          3
2  MM1  S3    cb      5          8
3  MM2  S3    mk      8          8
4  MM2  S4    bg     10         10
5  MM2  S4   dgd      1         10
6  MM4  S2    rd      2          7
7  MM4  S2    cb      2          7
8  MM4  S2   uyi      7          7

@ ज़ेलज़नी 7, क्या एक कॉलम द्वारा समूहीकरण के लिए आवेदन करने के लिए इस उत्तर को अपनाने का एक तरीका है और फिर 2 स्तंभों को देखना और उन दोनों में से अधिक प्राप्त करने के लिए अधिकतम करना है? मुझे वह काम नहीं मिला। वर्तमान में मेरे पास क्या है: ग्रेटर (मर्ज, मैक्सए, मैक्सबी): ए = मर्ज [मैक्सए] बी = मर्ज [मैक्सबी] अधिकतम रिटर्न (ए, बी) मर्जर.ग्रुपबी ("Search_Term")। लागू करें (ग्रेटर, "Ratio_x" "," अनुपात_य ")
गणितज्ञ

3
@ ज़ेलज़नी 7 मैं दूसरे, idxदृष्टिकोण का उपयोग कर रहा हूं । लेकिन, मैं केवल प्रत्येक समूह के लिए एक ही अधिकतम खर्च कर सकता हूं (और मेरे डेटा में कुछ डुप्लिकेट-अधिकतम है)। वहाँ अपने समाधान के साथ इस चारों ओर पाने के लिए एक रास्ता है?
3pitt

वास्तव में, यह मेरे लिए काम नहीं करता है। मैं समस्या को ट्रैक नहीं कर सकता, क्योंकि डेटाफ्रेम अगर बड़ा छोड़ दिया जाता है, लेकिन @ रानी द्वारा समाधान अच्छा काम करता है
लादेनकोव व्लादिस्लाव

हाय जोस्ज़नी, अगर मैं एक अधिकतम मूल्य के बजाय शीर्ष 3 अधिकतम पंक्ति लेना चाहता हूं, तो मैं आपका कोड कैसे मोड़ सकता हूं?
ज़ेफियर

transformविधि में पूल प्रदर्शन हो सकता है जब डेटा सेट काफी बड़ा होता है, तो पहले अधिकतम मूल्य प्राप्त करें फिर डेटाफ़्रेम को मर्ज करना बेहतर होगा।
वुड्स चेन

170

आप गणना द्वारा डेटाफ़्रेम को सॉर्ट कर सकते हैं और फिर डुप्लिकेट निकाल सकते हैं। मुझे लगता है कि यह आसान है:

df.sort_values('count', ascending=False).drop_duplicates(['Sp','Mt'])

4
बहुत अच्छा! लार्ज फ्रेम (25k पंक्तियों) के साथ तेज़
नोलन कॉनवे

2
उन लोगों के लिए जो पायथन के साथ कुछ नए हैं, आपको इसे एक नए चर में निर्दिष्ट करने की आवश्यकता होगी, यह वर्तमान df चर को नहीं बदलता है।
टायलर

1
@ आमिर या inplace = Trueतर्क के रूप में उपयोग करते हैंdrop_duplicates
TMrtSmith

5
यह एक महान जवाब है जब एक ही अधिकतम मान वाली पंक्तियों में से केवल एक की आवश्यकता होती है, हालांकि यह अपेक्षा के अनुरूप काम नहीं करता है यदि मुझे अधिकतम मूल्यों के साथ सभी पंक्तियों की आवश्यकता होती है।
वुड्स चेन

1
@WoodsChen, यह [sp, mt] के डुप्लिकेट को गिरा देता है, इसलिए आपके उदाहरण में, आउटपुट केवल एक पंक्ति होना चाहिए।
रानी

54

लागू करने के लिए आसान समाधान होगा: idxmax () फ़ंक्शन अधिकतम मानों के साथ पंक्तियों के सूचकांक प्राप्त करने के लिए। यह समूह में अधिकतम मूल्य वाली सभी पंक्तियों को फ़िल्टर कर देगा।

In [365]: import pandas as pd

In [366]: df = pd.DataFrame({
'sp' : ['MM1', 'MM1', 'MM1', 'MM2', 'MM2', 'MM2', 'MM4', 'MM4','MM4'],
'mt' : ['S1', 'S1', 'S3', 'S3', 'S4', 'S4', 'S2', 'S2', 'S2'],
'val' : ['a', 'n', 'cb', 'mk', 'bg', 'dgb', 'rd', 'cb', 'uyi'],
'count' : [3,2,5,8,10,1,2,2,7]
})

In [367]: df                                                                                                       
Out[367]: 
   count  mt   sp  val
0      3  S1  MM1    a
1      2  S1  MM1    n
2      5  S3  MM1   cb
3      8  S3  MM2   mk
4     10  S4  MM2   bg
5      1  S4  MM2  dgb
6      2  S2  MM4   rd
7      2  S2  MM4   cb
8      7  S2  MM4  uyi


### Apply idxmax() and use .loc() on dataframe to filter the rows with max values:
In [368]: df.loc[df.groupby(["sp", "mt"])["count"].idxmax()]                                                       
Out[368]: 
   count  mt   sp  val
0      3  S1  MM1    a
2      5  S3  MM1   cb
3      8  S3  MM2   mk
4     10  S4  MM2   bg
8      7  S2  MM4  uyi

### Just to show what values are returned by .idxmax() above:
In [369]: df.groupby(["sp", "mt"])["count"].idxmax().values                                                        
Out[369]: array([0, 2, 3, 4, 8])

4
यहां प्रश्नकर्ता निर्दिष्ट है "I want to get ALL the rows where count equals max in each group", जबकि idxmax Return[s] index of first occurrence of maximum over requested axis"डॉक्स (0.21) के अनुसार।
मैक्स पावर

1
यह एक महान समाधान है, लेकिन एक अलग समस्या के लिए
कार्लोस सूज़ा

33

अपेक्षाकृत बड़े डेटाफ़्रेम (~ 400k पंक्तियों) पर ज़ेलज़नी द्वारा सुझाए गए समाधान की कोशिश करने के बाद मैंने पाया कि यह बहुत धीमा है। यहां एक विकल्प है कि मुझे अपने डेटा सेट पर तेजी से परिमाण के आदेश चलाने के लिए मिला।

df = pd.DataFrame({
    'sp' : ['MM1', 'MM1', 'MM1', 'MM2', 'MM2', 'MM2', 'MM4', 'MM4', 'MM4'],
    'mt' : ['S1', 'S1', 'S3', 'S3', 'S4', 'S4', 'S2', 'S2', 'S2'],
    'val' : ['a', 'n', 'cb', 'mk', 'bg', 'dgb', 'rd', 'cb', 'uyi'],
    'count' : [3,2,5,8,10,1,2,2,7]
    })

df_grouped = df.groupby(['sp', 'mt']).agg({'count':'max'})

df_grouped = df_grouped.reset_index()

df_grouped = df_grouped.rename(columns={'count':'count_max'})

df = pd.merge(df, df_grouped, how='left', on=['sp', 'mt'])

df = df[df['count'] == df['count_max']]

1
वास्तव में यह बहुत तेज है। परिवर्तन बड़े डेटासेट के लिए धीमा प्रतीत होता है।
गोह

1
क्या आप यह समझाने के लिए टिप्पणी जोड़ सकते हैं कि प्रत्येक पंक्ति क्या करती है?
tommy.carstensen

fwiw: मुझे @Lazazny7 से अधिक सुरुचिपूर्ण दिखने वाला समाधान मिला ~ ~ 100K पंक्तियों के मेरे सेट के लिए निष्पादित करने में एक लंबा समय लगा, लेकिन यह बहुत जल्दी चला गया। (मैं अब एक तरह से अप्रचलित 0.13.0 चला रहा हूं, जो धीमेपन के लिए हो सकता है)।
रोलैंड

2
लेकिन ऐसा करने df[df['count'] == df['count_max']]से NaN पंक्तियां खो जाएंगी, साथ ही ऊपर दिए गए उत्तर भी।
क्यू ज़ूओ जुएल

मैं इस दृष्टिकोण का उपयोग करने का सुझाव देता हूं, बड़े डेटा फ़्रेम के लिए इसका उपयोग करने के लिए बहुत तेज़ है ।appy () या .agg ()।
तोय्या डी। सेर्डन

18

आपको sort_values+ का उपयोग करके समूह के साथ करने की आवश्यकता नहीं हो सकती हैdrop_duplicates

df.sort_values('count').drop_duplicates(['Sp','Mt'],keep='last')
Out[190]: 
    Sp  Mt Value  count
0  MM1  S1     a      3
2  MM1  S3    cb      5
8  MM4  S2   uyi      7
3  MM2  S3    mk      8
4  MM2  S4    bg     10

भी लगभग एक ही तर्क का उपयोग करके tail

df.sort_values('count').groupby(['Sp', 'Mt']).tail(1)
Out[52]: 
    Sp  Mt Value  count
0  MM1  S1     a      3
2  MM1  S3    cb      5
8  MM4  S2   uyi      7
3  MM2  S3    mk      8
4  MM2  S4    bg     10

न केवल यह अन्य समाधानों की तुलना में तेजी से परिमाण का एक क्रम है (कम से कम मेरे उपयोग के मामले के लिए), इसमें मूल डेटाफ़्रेम के निर्माण के हिस्से के रूप में बस जंजीर का अतिरिक्त लाभ है।
क्ले

मैं अपने सिर को सोच रहा था निश्चित रूप से यह सरल है, आपके शानदार जवाब के लिए धन्यवाद हमेशा के लिए श्री वेन।
दत्तनोविस

7

मेरे लिए, सबसे आसान समाधान मूल्य रखना होगा जब गिनती अधिकतम के बराबर होती है। इसलिए, निम्न एक पंक्ति आदेश पर्याप्त है:

df[df['count'] == df.groupby(['Mt'])['count'].transform(max)]

4

उपयोग groupbyऔर idxmaxतरीके:

  1. कर्नल dateको स्थानांतरित करें datetime:

    df['date']=pd.to_datetime(df['date'])
  2. maxस्तंभ का सूचकांक प्राप्त करें date, उसके बाद groupyby ad_id:

    idx=df.groupby(by='ad_id')['date'].idxmax()
  3. वांछित डेटा प्राप्त करें:

    df_max=df.loc[idx,]

आउट [54]:

ad_id  price       date
7     22      2 2018-06-11
6     23      2 2018-06-22
2     24      2 2018-06-30
3     28      5 2018-06-22

2
df = pd.DataFrame({
'sp' : ['MM1', 'MM1', 'MM1', 'MM2', 'MM2', 'MM2', 'MM4', 'MM4','MM4'],
'mt' : ['S1', 'S1', 'S3', 'S3', 'S4', 'S4', 'S2', 'S2', 'S2'],
'val' : ['a', 'n', 'cb', 'mk', 'bg', 'dgb', 'rd', 'cb', 'uyi'],
'count' : [3,2,5,8,10,1,2,2,7]
})

df.groupby(['sp', 'mt']).apply(lambda grp: grp.nlargest(1, 'count'))

2

यह महसूस करते हुए कि "" "" निरर्थक "समूह वस्तु पर लागू करना ठीक काम करता है:

अतिरिक्त लाभ - यदि आवश्यक हो तो शीर्ष एन मान प्राप्त कर सकते हैं :

In [85]: import pandas as pd

In [86]: df = pd.DataFrame({
    ...: 'sp' : ['MM1', 'MM1', 'MM1', 'MM2', 'MM2', 'MM2', 'MM4', 'MM4','MM4'],
    ...: 'mt' : ['S1', 'S1', 'S3', 'S3', 'S4', 'S4', 'S2', 'S2', 'S2'],
    ...: 'val' : ['a', 'n', 'cb', 'mk', 'bg', 'dgb', 'rd', 'cb', 'uyi'],
    ...: 'count' : [3,2,5,8,10,1,2,2,7]
    ...: })

## Apply nlargest(1) to find the max val df, and nlargest(n) gives top n values for df:
In [87]: df.groupby(["sp", "mt"]).apply(lambda x: x.nlargest(1, "count")).reset_index(drop=True)
Out[87]:
   count  mt   sp  val
0      3  S1  MM1    a
1      5  S3  MM1   cb
2      8  S3  MM2   mk
3     10  S4  MM2   bg
4      7  S2  MM4  uyi

2

समूह वस्तु पर "निरर्थक" का उपयोग करने का प्रयास करें। नॉर्लेस्ट का उपयोग करने का लाभ यह है कि यह उन पंक्तियों के सूचकांक को लौटाता है जहां से "सबसे अधिक आइटम (ओं) को" लाया गया था। नोट: हम अपने सूचकांक के दूसरे (1) तत्व को स्लाइस करते हैं क्योंकि इस मामले में हमारे सूचकांक में tuples शामिल हैं (जैसे (s1, 0))।

df = pd.DataFrame({
'sp' : ['MM1', 'MM1', 'MM1', 'MM2', 'MM2', 'MM2', 'MM4', 'MM4','MM4'],
'mt' : ['S1', 'S1', 'S3', 'S3', 'S4', 'S4', 'S2', 'S2', 'S2'],
'val' : ['a', 'n', 'cb', 'mk', 'bg', 'dgb', 'rd', 'cb', 'uyi'],
'count' : [3,2,5,8,10,1,2,2,7]
})

d = df.groupby('mt')['count'].nlargest(1) # pass 1 since we want the max

df.iloc[[i[1] for i in d.index], :] # pass the index of d as list comprehension

यहां छवि विवरण दर्ज करें


1

मैं कई समूह संचालन के लिए इस कार्यात्मक शैली का उपयोग कर रहा हूं:

df = pd.DataFrame({
   'Sp' : ['MM1', 'MM1', 'MM1', 'MM2', 'MM2', 'MM2', 'MM4', 'MM4', 'MM4'],
   'Mt' : ['S1', 'S1', 'S3', 'S3', 'S4', 'S4', 'S2', 'S2', 'S2'],
   'Val' : ['a', 'n', 'cb', 'mk', 'bg', 'dgb', 'rd', 'cb', 'uyi'],
   'Count' : [3,2,5,8,10,1,2,2,7]
})

df.groupby('Mt')\
  .apply(lambda group: group[group.Count == group.Count.max()])\
  .reset_index(drop=True)

    sp  mt  val  count
0  MM1  S1    a      3
1  MM4  S2  uyi      7
2  MM2  S3   mk      8
3  MM2  S4   bg     10

.reset_index(drop=True) समूह-सूचकांक को गिराकर आपको मूल सूचकांक में वापस लाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.