pandas 取 groupby 后每个分组的前 N 行

原始数据如下:

(图是从 excel 截的,最左1行不是数据,是 excel 自带的行号,为了方便说明截进来的)

除去首行是标题外,有效数据为 28行 x 4列

目前的需求是根据 partition 分组,然后取每组的前 2 行,如果不考虑排序,代码如下:
(把head()里面的数字改成 n 就可以取 n 行)

import pandas as pd

esp_df = pd.read_excel('excel文件路径', sheet_name='Sheet名')
esp_df.groupby(['partition', 'create_time', 'last_modified_time']).mean().reset_index(drop=False).groupby('partition').head(2)

结果如下:

分别说明如下:

  • groupby:分组,这里是根据数据中的 3 列来一起分组,因为我们并不需要做聚合运算,所以这么取可以保留原始数据不变。原始数据只有 4 列,这里 groupby 了 3 列,只剩下 size(其实把 size 放进去一起 groupby 也没问题)
  • mean:求平均值,但是在这里没用,因为上一步的 groupby 取了前面的 3 列,在本例中,前 3 列并在一起就能得到一个唯一的一行,所以这里其实也只是每一行数据自己求平均数,结果等于它本身。同理,这里替代成求和函数 sum() 也是一样的。但是不能省略,因为**省略后它就是一个 DataFrameGroupBy 类型的变量,不是 DataFrame,而 DataFrameGroupBy 是没有后面的 reset_index 方法的
  • reset_index:重置索引,groupby 之后,结果集的索引就变成了 groupby 里面的 key,这个 reset_index 把这个索引重新退回为数据。
    举例说明,在应用 reset_index 之前,即使用 mean() 之后的数据是这样的:

可以看到左边的 3 列,也就是 groupby key 的 partition、create_time、last_modified_time 是加粗了的,说明此时这 3 列都是索引;而且 partition 因为有相同的行,还被合并了。显然这不是我们想要的。reset_index 把它们重新放回到数据列里

参数中的 drop 作用是是否保留(重置前)的索引
数据就又回来了,索引变成了原来默认的(0123...)

  • groupby:再次根据 partition 分组
  • head: 取每个分组的前 n 行

如果要排序

本例中,如果要先根据 partition 分组,然后再根据 size 倒序(从大到小)再取前 2 行,则代码如下:

esp_df.groupby(['partition']).apply(lambda x: x.sort_values(["size"], ascending = False)).reset_index(drop=True).groupby('partition').head(2)

结果如下:

posted @ 2021-10-19 11:07  东围居士  阅读(1673)  评论(2编辑  收藏  举报