Python数据处理神器pandas,图解剖析分组聚合处理

2021-09-01 15:18:55 浏览数 (1)

点击上方"数据大宇宙",设为星标,干货资料,第一时间送到!

前言

身边有许多正在学习 Python 的 pandas 库做数据处理的小伙伴们都遇到一个问题——分组聚合。 网上很多这方面的资料,几乎都是列出一系列诸如 "xx方法不能用 Python 内置函数" 之类的规则。小伙伴都说记不住啊。 本文尝试把内部原理机制教会你,让你无需记忆这么多死板的规则即可灵活运用。

本文主要涉及的函数和要的:

  • groupby
  • apply
  • agg
  • transform
  • 总结这些函数的特点,说明解决思路。

数据

本文大部分例子的数据,如下图定义:


分组

物以类聚,人以群分。数据处理时同样需要按类别分组处理,面对这样的高频功能需求, pandas 中提供 groupby 方法进行分组。

按 class 进行分组 如下图的代码:

  • 17-19行,两行的写法是一样的。
  • 注意一点,只是调用 groupby 方法,没有进行任何的处理,只返回一个迭代器。
  • 行21,只有当你需要数据时,才会真正执行分组的运算
  • 返回结果是一个元组(key,每个组的记录的DataFrame)。

你还可以传入具体的数据,他实际会按你传入的数据的值进行分组。


怎么处理这些组?

分组只是处理的第一步,一般来说,我们不应该用遍历去处理每个组。 在pandas中,为我们提供了一些聚合方法用于处理组数据。

apply

apply 只是一种对每个分组进行处理的通用方式。来看看流程动图:

  • apply 方法中传入一个用于处理的方法。
  • apply 会把每个分组以一个DataFrame的形式,传入处理方法的首个参数中。
  • 因此,为什么很多文章说,apply 不能使用 python 内置函数,实际是 python 内置函数不能处理 DataFrame 而已。
  • apply 在处理的最后一步,把每个分组的处理结果合并成一个 DataFrame 返回。

apply 中还可以传入自定义函数,比如我们希望用 value 减去 age 。如下:

  • 注意一点,每个分组的处理结果同样可以是一个多行的 DataFrame 。
  • 合并后,由于同个分组有多行数据,为了区别开来,合并结果的索引部分会带上数据源的索引。

有时候,自定义函数也需要额外的参数。 比如,希望返回 value 列减去指定值的新列

  • 在调用 apply 时,传入命名参数值即可。
  • 因为自定义首个参数是 DataFrame ,因此可以指定列表名,以此针对某列进行处理。

agg

agg 的处理流程与 apply 基本一致。当注意 agg 的处理函数的首个参数是 Series。

  • 注意,处理函数是分别处理每个字段(Series)。
  • 因此,不要在自定义函数中指定字段。
  • 为什么很多文章说 agg 可以使用 python 内置函数,就是因为 python 内置函数可以处理 Series 。

下面是 agg 的自定义函数例子。


transform

当我们需要分组处理的中间结果,但不需要分组后的结果,则可以使用 transform 。 看其流程机制:

  • transform 是为了保持结果的记录行数与原数据保持一致。
  • transform 流程机制与 agg 几乎一样。区别在于最后的合并。
  • 如果 transform 的处理函数返回是一个值,那么为了与原数据行数保持一致,因此会把组内的值在组内复制(广播)。
  • transform 的处理函数还可以返回一个列(也就是有多行),但必须要求最终合并结果与原数据行数一致。
  • 返回的结果不会出现分组的 key 字段。

看起来 transform 有不少规则需要记住。其实记住2点即可。

  • transform 是为了保持结果的记录行数与原数据保持一致
  • 处理函数的首个参数是字段(Series)

至于处理函数可以返回什么东西,完全是遵从点1。

特点

即使你学会了上述的知识点,但当你遇上问题时,还是会觉得无从入手。因为没有归纳他们的的特点。我们一起来看看。

groupby 分组本质上是为了按某个组别分别处理。而分组处理的结果无非3种:

  • 结果会被压缩。比如原数据有100行2个组,分组后的结果就只有2行了。
  • 结果保持原样。比如希望用每行的年龄减去所在组的平均年龄。处理结果还是100行,只是中间过程需要分组的计算结果。
  • 结果部分被压缩。比如本文中的例子,求出每组的 top 2 的人选。

针对 apply,agg,transform 的特点可以归纳如下:

  • 如果需要按组压缩结果,那么首选考虑 agg 。
  • 如果需要保持原样,那么考虑 transform 和 apply 。
  • 如果需要部分被压缩,比如 top n 问题,那么考虑使用 apply 。

例子

例子1:使用本文的例子数据,如果 value 存在缺失值则用组内均值填充。

  • 从所需结果的情况分析,是完全保持原样,因此选用 transform 。
  • 一般在使用 transform 时,在 groupby 之后指定一列。
  • 自定义函数中可以很容易求得 value 的均值。

例子2:使用本文的例子数据,以 value 列为标准,得出每个分组的 top 2的人。

  • 这是部分被压缩的需求,因此选用 apply 。
  • 自定义函数中的首个参数是整块分组的数据,因此可以进行任意字段排序。然后进行选取返回即可。

最后

归纳好知识点,就能让自己少记住一些规则,灵活运用。

如果觉得本文对你有所帮助,记得关注、评论、转发、收藏噢~


0 人点赞