概述
GroupBy对象支持迭代、查看组信息、按组名提取子组,以及统计各组大小。
2.1 迭代组
对
GroupBy对象进行for循环,每次返回二元组:组名 与 子组数据。
import pandas as pd
df = pd.DataFrame({
"部门": ["A", "A", "B", "B", "C"],
"员工": ["张三", "李四", "王五", "赵六", "孙七"],
"薪资": [8000, 9500, 12000, 11000, 9000],
})
grouped = df.groupby("部门")
# 迭代每个组
for name, group in grouped:
print(f"=== 部门: {name} ===")
print(group)
print()
# 多列分组时,name 是一个元组
grouped2 = df.groupby(["部门", "员工"])
for name, group in grouped2:
print(name) # 如 ('A', '张三')性能提示
迭代组通常较慢,仅适合调试或小数据场景;大规模场景建议使用向量化的聚合操作。
2.2 groups 与 indices
| 属性 | 说明 |
|---|---|
groups | 字典,键为组名,值为该组对应的行索引(Index 对象) |
indices | 字典,键为组名,值为该组对应的位置索引(ndarray) |
# groups:返回行标签索引
grouped.groups
# 输出类似:
# {'A': [0, 1], 'B': [2, 3], 'C': [4]}
# 多列分组时键为元组
grouped2.groups
# {('A', '张三'): [0], ('A', '李四'): [1], ...}
# indices:返回位置整数索引
grouped.indices
# {'A': array([0, 1]), 'B': array([2, 3]), 'C': array([4])}2.3 get_group()
get_group(name)返回指定组名的子 DataFrame / Series,组名需与分组键完全匹配。
# 按组名提取
df.groupby("部门").get_group("A")
# 多列分组时传入元组
df.groupby(["部门", "员工"]).get_group(("A", "张三"))
# 时间分组提取
ts_df = pd.DataFrame(
{"值": range(10)},
index=pd.date_range("2024-01-01", periods=10, freq="D"),
)
weekly = ts_df.groupby(pd.Grouper(freq="W"))
weekly.get_group("2024-01-07")2.4 size()
size()返回各组包含的行数(元素个数),与count()不同:size()不忽略NaN。
df.groupby("部门").size()
# 输出:
# 部门
# A 2
# B 2
# C 1
# dtype: int64
# 多列分组大小
df.groupby(["部门", "性别"]).size()
# 输出为 DataFrame,并使用列名 "size"
df.groupby("部门").size().reset_index(name="数量")
# 对比 count():count 忽略 NaN
df_nan = pd.DataFrame({"部门": ["A", "A"], "薪资": [8000, None]})
df_nan.groupby("部门")["薪资"].size() # 2
df_nan.groupby("部门")["薪资"].count() # 12.5 ngroups
ngroups返回分组总数。
df.groupby("部门").ngroups # 3
df.groupby(["部门", "性别"]).ngroups # 5(实际存在的组数)
# 分类数据时包含所有类别
import pandas as pd
cat_df = pd.DataFrame({
"类别": pd.Categorical(["a", "b"], categories=["a", "b", "c"]),
"值": [1, 2],
})
cat_df.groupby("类别", observed=True).ngroups # 2
cat_df.groupby("类别", observed=False).ngroups # 3相关笔记
- 上一节:分组与聚合-1-groupby创建
- 下一节:分组与聚合-3-聚合