我如何找到所有行的熊猫DataFrame有最大的值为计数列,分组后['Sp','Mt']列?

例1:下面的DataFrame,我用['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**
2  MM1  S3   cb     **5**
3  MM2  S3   mk     **8**
4  MM2  S4   bg     **10** 
8  MM4  S2   uyi    **7**

例2:这个DataFrame,我用['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等于max的所有行,如下所示:

   Sp   Mt   Value  count
4  MM2  S4   bg     10
7  MM4  S2   cb     8
8  MM4  S2   uyi    8

当前回答

您可能不需要执行groupby(),而是同时使用sort_values + drop_duplicate

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

其他回答

其中许多都是很好的答案,但是为了帮助显示可伸缩性,在280万行具有不同数量重复的数据上显示了一些惊人的差异。对我的数据来说,最快的是排序,然后删除重复(删除所有但最后稍微快于排序降序和删除所有但第一个)

Sort Ascending, Drop duplicate keep last (2.22 s) Sort Descending, Drop Duplicate keep First (2.32 s) Transform Max within the loc function (3.73 s) Transform Max storing IDX then using loc select as second step (3.84 s) Groupby using Tail (8.98 s) IDMax with groupby and then using loc select as second step (95.39 s) IDMax with groupby within the loc select (95.74 s) NLargest(1) then using iloc select as a second step (> 35000 s ) - did not finish after running overnight NLargest(1) within iloc select (> 35000 s ) - did not finish after running overnight

如你所见,Sort比transform快1/3,比groupby快75%。其他的都要慢40倍。在小型数据集中,这可能无关紧要,但如您所见,这可能会对大型数据集产生重大影响。

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'))

您可以根据计数对dataFrame进行排序,然后删除重复项。我认为这样更简单:

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

对我来说,最简单的解决方案是当count等于最大值时保持value。因此,以下一行命令就足够了:

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

意识到“应用”“nmaximum”到groupby对象同样有效:

额外的优势-也可以获取前n个值,如果需要:

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