从熊猫数据框中选择排序组的第一行

use*_*974 4 python group-by numpy dataframe pandas

假设我在熊猫中有一个数据框,如下所示:

campaignname    category_type    amount
A               cat_A_0            2.0
A               cat_A_1            1.0
A               cat_A_2            3.0
A               cat_A_2            3.0
A               cat_A_2            4.0
B               cat_B_0            3.0
C               cat_C_0            1.0
C               cat_C_1            2.0
Run Code Online (Sandbox Code Playgroud)

我正在使用以下代码df按不同的列将上述数据框(例如,为它分配了变量name )分组,如下所示:

for name, gp in df.groupby('campaignname'):
    sorted_gp = gp.groupby(['campaignname', 'category_type']).sum().sort_values(['amount'], ascending=False)
    # I'd like to know how to select this in a cleaner/more concise way
    first_row = [sorted_gp.iloc[0].name[0], sorted_gp.iloc[0].name[1], sorted_gp.iloc[0].values.tolist()[0]]
Run Code Online (Sandbox Code Playgroud)

上面代码的目的是首先groupby将原始数据放在campaignname列中,然后在每个结果组中,我都希望再次按campaignname和进行分组category_type,最后,按amount列进行排序以选择出现的第一行(amount每个组中得分最高的一个。特别是对于上面的示例,我想获得如下结果:

first_row = ['A', 'cat_A_2', 4.0] # for the first group
first_row = ['B', 'cat_B_0', 3.0] # for the second group
first_row = ['C', 'cat_C_1', 2.0] # for the third group
Run Code Online (Sandbox Code Playgroud)

等等

如您所见,我正在使用一种相当(丑陋)的“丑陋”方式来检索每个已排序组的第一行,但是由于我是熊猫的新手,所以我不知道一种更好/更清洁的方法完成这个。如果有人能让我知道从熊猫数据框中选择排序组中第一行的方法,我将不胜感激。预先感谢您的回答/建议!

Max*_*axU 6

IIUC您可以通过以下方式进行操作:

In [83]: df.groupby('campaignname', as_index=False) \
           .apply(lambda x: x.nlargest(1, columns=['amount'])) \
           .reset_index(level=1, drop=1)
Out[83]:
  campaignname category_type  amount
0            A       cat_A_2     4.0
1            B       cat_B_0     3.0
2            C       cat_C_1     2.0
Run Code Online (Sandbox Code Playgroud)

要么:

In [76]: df.sort_values('amount', ascending=False).groupby('campaignname').head(1)
Out[76]:
  campaignname category_type  amount
4            A       cat_A_2     4.0
5            B       cat_B_0     3.0
7            C       cat_C_1     2.0
Run Code Online (Sandbox Code Playgroud)