分类汇总

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

class order max_speed
falcon bird Falconiformes 389.0
parrot bird Psittaciformes 24.0
lion mammal Carnivora 80.2
monkey mammal Primates NaN
leopard mammal Carnivora 58.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

A B C D
0 foo one 0.106162 -0.093786
1 bar one -0.179389 2.213905
2 foo two -0.190954 0.082038
3 bar three 0.312979 1.034273
4 foo two 1.052136 -0.130627
5 bar two -1.220164 1.215908
6 foo one -0.926031 -1.477368
7 foo three 0.157087 1.622384

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

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

求和

grouped.sum()

C D
A
bar -1.086574 4.464086
foo 0.198399 0.002641

平均值

grouped.mean()

C D
A
bar -0.362191 1.488029
foo 0.039680 0.000528

中位数

grouped.median()

C D
A
bar -0.179389 1.215908
foo 0.106162 -0.093786

最小值

grouped.min()

C D
A
bar -1.220164 1.034273
foo -0.926031 -1.477368

最大值

grouped.max()

C D
A
bar 0.312979 2.213905
foo 1.052136 1.622384

标准差

grouped.std()

C D
A
bar 0.782748 0.635154
foo 0.712226 1.100833

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

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

C D
sum mean sum mean
A
bar -1.086574 -0.362191 4.464086 1.488029
foo 0.198399 0.039680 0.002641 0.000528

次序

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

Name Attempt GRE Score
0 Jim First 298
1 Jim Second 321
2 Jim Third 314
3 Pam First 318
4 Pam Second 330

返回每个人最后一次 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

Name Attempt GRE Score Rank
0 Jim First 298 3
1 Jim Second 321 1
2 Jim Third 314 2
3 Pam First 318 2
4 Pam Second 330 1

如要给每组数据都排序,建议先对原 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