分类汇总

import pandas as pd
import numpy as np

分类汇总 group by 指的是如下的一个或多个步骤的数据分组:

  • Splitting: 根据某些标准将数据分成若干组。
  • Applying: 将一个函数独立应用于每个组。
  • Combining: 将结果合并到数据结构中。

其中,拆分步骤最简单。事实上,在许多情况下,我们可能希望将数据集分成若干组,并对这些组进行处理。

在应用步骤中,我们可能希望执行以下操作之一:

  • Aggregation: 计算每组的汇总统计数据。例如计算每组的和 sum 以及平均值 means,或者数每组记录的个数。
  • Transformation: 执行一些特定于组的计算,并返回一个相似的索引对象。例如获得每组排序后的第一个数据。
  • Filtration: 根据评估为真或假的分组计算,丢弃一些分组。例如丢弃属于只有少数成员的组的数据,或者根据组和或平均值过滤数据。

分组

pandas 对象可以在其任意轴上拆分。分组的抽象定义是提供标签到组名的映射。分组需要创建 GroupBy 对象。

df = pd.DataFrame(
    [
        ("bird", "Falconiformes", 389.0),
        ("bird", "Psittaciformes", 24.0),
        ("mammal", "Carnivora", 80.2),
        ("mammal", "Primates", np.nan),
        ("mammal", "Carnivora", 58),
    ],
    index=["falcon", "parrot", "lion", "monkey", "leopard"],
    columns=("class", "order", "max_speed"),
)
df

classordermax_speed
falconbirdFalconiformes389.0
parrotbirdPsittaciformes24.0
lionmammalCarnivora80.2
monkeymammalPrimatesNaN
leopardmammalCarnivora58.0

按行分组。

df.groupby('class')
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000001BC34299A10>

按多个字段分组。

df.groupby(['class', 'order'])
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000001BC3427E710>

通常一张数据表每一行表示一条记录,每一列表示一个字段。因而分类汇总是针对字段,对每条记录(按行)进行分组。如果确实有按列进行分组的需求,将 DataFrame 对象转置即可。

应用与合并

汇总

df = pd.DataFrame(
    {
        "A": ["foo", "bar", "foo", "bar", "foo", "bar", "foo", "foo"],
        "B": ["one", "one", "two", "three", "two", "two", "one", "three"],
        "C": np.random.randn(8),
        "D": np.random.randn(8),
    }
)
df

ABCD
0fooone0.106162-0.093786
1barone-0.1793892.213905
2footwo-0.1909540.082038
3barthree0.3129791.034273
4footwo1.052136-0.130627
5bartwo-1.2201641.215908
6fooone-0.926031-1.477368
7foothree0.1570871.622384

GroupBy 对象后索引 column 表示需要汇总的属性,会返回一个新的 GroupBy 对象。

grouped = df.groupby('A')[['C', 'D']]

求和

grouped.sum()

CD
A
bar-1.0865744.464086
foo0.1983990.002641

平均值

grouped.mean()

CD
A
bar-0.3621911.488029
foo0.0396800.000528

中位数

grouped.median()

CD
A
bar-0.1793891.215908
foo0.106162-0.093786

最小值

grouped.min()

CD
A
bar-1.2201641.034273
foo-0.926031-1.477368

最大值

grouped.max()

CD
A
bar0.3129792.213905
foo1.0521361.622384

标准差

grouped.std()

CD
A
bar0.7827480.635154
foo0.7122261.100833

可以使用 agg 来使用任何可以进行汇总和统计的函数,包括用户自定义的函数。

grouped.agg(['sum', 'mean'])

CD
summeansummean
A
bar-1.086574-0.3621914.4640861.488029
foo0.1983990.0396800.0026410.000528

次序

df = pd.DataFrame({
    'Name': ['Jim', 'Jim', 'Jim', 'Pam', 'Pam'],
    'Attempt': ['First', 'Second', 'Third', 'First', 'Second'],
    'GRE Score': [298, 321, 314, 318, 330]
})
df

NameAttemptGRE Score
0JimFirst298
1JimSecond321
2JimThird314
3PamFirst318
4PamSecond330

返回每个人最后一次 GRE 考试成绩:

df.groupby('Name')['GRE Score'].last()
Name
Jim    314
Pam    330
Name: GRE Score, dtype: int64

返回每个人第一次 GRE 考试成绩:

df.groupby('Name')['GRE Score'].first()
Name
Jim    298
Pam    318
Name: GRE Score, dtype: int64

使用 nth 可以返回第任意次 GRE 考试成绩:

df.groupby('Name')['GRE Score'].nth(1)
1    321
4    330
Name: GRE Score, dtype: int64

排序

给每次 GRE 考试都加上名次。

df['Rank'] = df.groupby('Name')['GRE Score'].rank(ascending=False).astype(int)
df

NameAttemptGRE ScoreRank
0JimFirst2983
1JimSecond3211
2JimThird3142
3PamFirst3182
4PamSecond3301

如要给每组数据都排序,建议先对原 DataFrame 对象排序,再分组。

df.sort_values('GRE Score', ascending=False).groupby('Name')['GRE Score'].first()
Name
Jim    321
Pam    330
Name: GRE Score, dtype: int64
Previous
Next