GroupBy#

cuDF 支持 Pandas groupby API 的一小部分(但很重要)子集。

支持的操作摘要#

  1. 按一列或多列分组

  2. 基本的聚合操作,例如 “sum”、“mean” 等。

  3. 分位数聚合

  4. 一种“collect”或 list 聚合操作,用于将组中的值收集到列表中

  5. 聚合时自动排除具有不支持的数据类型(“冗余”列)的列

  6. 迭代 GroupBy 对象的组

  7. GroupBy.groups API,返回从分组键到行标签的映射

  8. GroupBy.apply API,用于对每个组执行任意操作。请注意,与等效的 Pandas 函数相比,此功能非常有限。有关更多详细信息,请参阅 apply 部分。

  9. GroupBy.pipe,类似于 Pandas

分组#

通过按一列或多列对 SeriesDataFrame 的值进行分组来创建 GroupBy 对象

>>> import cudf
>>> df = cudf.DataFrame({'a': [1, 1, 1, 2, 2], 'b': [1, 1, 2, 2, 3], 'c': [1, 2, 3, 4, 5]})
>>> df
   a  b  c
0  1  1  1
1  1  1  2
2  1  2  3
3  2  2  4
4  2  3  5
>>> gb1 = df.groupby('a')  # grouping by a single column
>>> gb2 = df.groupby(['a', 'b'])  # grouping by multiple columns
>>> gb3 = df.groupby(cudf.Series(['a', 'a', 'b', 'b', 'b']))  # grouping by an external column

警告

与 Pandas 不同,cuDF 默认使用 sort=False 以获得更好的性能,这不保证结果中组的特定顺序。

例如

>>> df = cudf.DataFrame({'a' : [2, 2, 1], 'b' : [42, 21, 11]})
>>> df.groupby('a').sum()
   b
a
2  63
1  11
>>> df.to_pandas().groupby('a').sum()
   b
a
1  11
2  63

设置 sort=True 将产生类似 Pandas 的输出,但会牺牲一些性能

>>> df.groupby('a', sort=True).sum()
   b
a
1  11
2  63

按索引级别分组#

您还可以按 MultiIndex 的一个或多个级别进行分组

>>> df = cudf.DataFrame(
...     {'a': [1, 1, 1, 2, 2], 'b': [1, 1, 2, 2, 3], 'c': [1, 2, 3, 4, 5]}
... ).set_index(['a', 'b'])
...
>>> df.groupby(level='a')

The Grouper 对象#

当列和级别同名时,可以使用 Grouper 来区分它们

>>> df
   b  c
b
1  1  1
1  1  2
1  2  3
2  2  4
2  3  5
>>> df.groupby('b', level='b')  # ValueError: Cannot specify both by and level
>>> df.groupby([cudf.Grouper(key='b'), cudf.Grouper(level='b')])  # OK

聚合#

组上的聚合通过 agg 方法支持

>>> df
   a  b  c
0  1  1  1
1  1  1  2
2  1  2  3
3  2  2  4
4  2  3  5
>>> df.groupby('a').agg('sum')
   b  c
a
1  4  6
2  5  9
>>> df.groupby('a').agg({'b': ['sum', 'min'], 'c': 'mean'})
    b        c
  sum min mean
a
1   4   1  2.0
2   5   2  4.5
>>> df.groupby("a").corr(method="pearson")
          b          c
a
1 b  1.000000  0.866025
  c  0.866025  1.000000
2 b  1.000000  1.000000
  c  1.000000  1.000000

下表总结了可用的聚合以及支持它们的类型

聚合 / 数据类型

数值

日期时间

字符串

分类

列表

Struct

区间

十进制

count

size

sum

idxmin

idxmax

min

max

mean

var

std

quantile

median

nunique

nth

collect

unique

corr

cov

GroupBy apply#

要对每个组应用函数,请使用 GroupBy.apply() 方法

>>> df
   a  b  c
0  1  1  1
1  1  1  2
2  1  2  3
3  2  2  4
4  2  3  5
>>> df.groupby('a').apply(lambda x: x.max() - x.min())
   a  b  c
a
0  0  1  2
1  0  1  1

限制#

  • apply 的工作方式是将提供的函数依次应用于每个组,然后将结果连接在一起。这可能非常慢,特别是对于大量小分组。对于少量大分组,它可以提供可接受的性能。

  • 结果可能并非总是与 Pandas 完全匹配。例如,cuDF 可能会返回包含单列的 DataFrame,而 Pandas 返回 Series。可能需要进行一些后处理才能匹配 Pandas 的行为。

  • cuDF 不支持 Pandas 使用 apply 支持的一些特殊情况,例如在可调用对象中调用 describe

Transform#

.transform() 方法按组进行聚合,并将结果广播到组的大小,从而生成一个与输入 Series/DataFrame 大小相同的 Series/DataFrame。

>>> import cudf
>>> df = cudf.DataFrame({'a': [2, 1, 1, 2, 2], 'b': [1, 2, 3, 4, 5]})
>>> df.groupby('a').transform('max')
   b
0  5
1  3
2  3
3  5
4  5

滚动窗口计算#

使用 GroupBy.rolling() 方法对每个组执行滚动窗口计算

>>> df
   a  b  c
0  1  1  1
1  1  1  2
2  1  2  3
3  2  2  4
4  2  3  5

对每个组执行窗口大小为 2 的滚动窗口求和

>>> df.groupby('a').rolling(2).sum()
        a     b     c
a
1 0  <NA>  <NA>  <NA>
  1     2     2     3
  2     2     3     5
2 3  <NA>  <NA>  <NA>
  4     4     5     9