HOWTO · Pandas

Pandas 由两列来 groupby

本教程讲解了我们如何在 Pandas 中将 DataFrame.groupby()方法应用于两列,以将 DataFrame 分成几组。

本页内容

按两列对行分组时,将列标签组成的列表传给 DataFrame.groupby()。每种不同的值组合都会构成一个组。下面的示例使用同一个包含六行的 DataFrame 来查看这些分组、统计各组的行数,并找出每种就业状态对应的最大子组。请在已安装 pandas 的环境中运行;此处不声称示例已执行。

按两列对 DataFrame 分组

列表 ['Gender', 'Employed'] 表示让 pandas 同时按这两列分组。例如,只有当两个值都匹配时,一行才属于 Female/Yes 组。下面的完整脚本可以独立运行,后续每一步都能使用同一份数据。

本节中的代码以及显示的标签或输出仍为英文。

import pandas as pd

data = pd.DataFrame(
    {
        "Name": ["Jennifer", "Travis", "Bob", "Emma", "Luna", "Anish"],
        "Gender": ["Female", "Male", "Male", "Female", "Female", "Male"],
        "Employed": ["Yes", "No", "Yes", "No", "Yes", "No"],
        "Age": [30, 28, 27, 24, 28, 25],
    }
)

groups = data.groupby(["Gender", "Employed"])

print("Groups:")
for group_key, group_rows in groups:
    print(f"{group_key}: {len(group_rows)} rows")

counts = groups.size().reset_index(name="Count")
print("\nRows per pair:")
print(counts.to_string(index=False))

largest = groups.size().groupby(level="Employed").max()
print("\nLargest subgroup per employment value:")
print(largest.to_string())

本节代码以及其中显示的标签和输出仍为英文。

遍历生成的分组

遍历 groups 时,每种实际出现的组合都会产生一对值 (group_key, group_rows)。这里,group_key 按顺序包含 Gender 和 Employed 的值;group_rows 则是包含对应源数据行的 DataFrame。可以直接使用遍历得到的 DataFrame;再用 get_group() 获取一次会重复查找。默认情况下,pandas 会按组键排序,而不保留各组在输入数据中的先后顺序;每个组内的行仍保持原有的相对顺序。

统计每个组的行数

groups.size() 会返回每个两列组合组中的行数。调用 reset_index(name="Count") 会将两个分组层级及其计数转换为普通列,便于展示或后续处理。即使 Age 这样的非分组字段包含缺失值,size() 仍会统计该行;如果改为统计某个具体列,则只会计数该列的非空值,结果可能不同。因此,Count 列表示每个 Gender/Employed 组合中的行数,而不是已填写的姓名数或年龄数。

找出列中每个值对应的最大分组

最后一个表达式先取得各组合的计数,再按该 Series 的 Employed 索引层级分组,并应用 max()。结果是每种就业状态下最大的 Gender 子组行数。在这份数据中,Female/Yes 组和 Male/No 组都各有两行,因此两种就业状态对应的最大子组行数都是二。这是对子组计数取最大值;它不会选出底层数据行,也不会指出哪个 Gender 达到了最大值。另有单独的文档介绍 max() 方法。