我如何找到所有行的熊猫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和idxmax方法:

将col date转换为datetime: df(“日期”)= pd.to_datetime (df(“日期”)) 在groupyby ad_id之后,获取列日期的Max索引: idx = df.groupby(=“ad_id”)(“日期”).idxmax () 获取所需数据: 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

其他回答

简单的解决方案是应用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])

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

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

其中许多都是很好的答案,但是为了帮助显示可伸缩性,在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倍。在小型数据集中,这可能无关紧要,但如您所见,这可能会对大型数据集产生重大影响。

尝试在groupby对象上使用" nmaximum "。使用nmaximum的优点是它返回“第n个最大项”所在行的索引。 注意:我们对索引的第二个(1)元素进行切片,因为在这种情况下,我们的索引由元组(例如。(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

您可能不需要执行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