cover

走马

陈粒

分组聚合排序

分组聚合排序

分组、聚合、排序#

准备基础数据#

先构建一份包含分组、聚合特征的员工数据,后续示例都基于这份数据:

import pandas as pd
import numpy as np
# 员工基础数据(含城市、部门、薪资等分组维度)
data = {
"姓名": ["张三", "李四", "王五", "赵六", "钱七", "孙八"],
"年龄": [20, 25, 22, 28, 30, 27],
"城市": ["北京", "上海", "广州", "北京", "深圳", "北京"],
"薪资": [8000, 12000, 9500, 15000, 18000, 11000],
"部门": ["技术部", "销售部", "技术部", "销售部", "技术部", "销售部"]
}
df = pd.DataFrame(data, index=["员工1", "员工2", "员工3", "员工4", "员工5", "员工6"])
# 新增薪资等级(方便分组)
df["薪资等级"] = np.where(df["薪资"] > 10000, "高", "中")
print("原始数据:")
print(df)

一、分组聚合(GroupBy + 聚合)#

核心逻辑:「拆分 - 应用 - 合并」#

  1. 拆分:把 DataFrame 按指定列(如 “城市”“部门”)分成多个小组;
  2. 应用:对每个小组的指定列(如 “薪资”“年龄”)执行聚合函数(如求均值、总和);
  3. 合并:把每个小组的聚合结果汇总成新的 DataFrame。

1. 基础分组聚合(单分组列 + 单聚合函数)#

语法df.groupby(分组列)[聚合列].聚合函数()

常用聚合函数:mean()(均值)、count()(计数)、sum()(总和)、max()(最大值)、min()(最小值)、median()(中位数)。

示例 1:按「城市」分组,统计每个城市的薪资平均值#

df_city_salary = df.groupby("城市")["薪资"].mean()
print("\n按城市分组的薪资均值:")
print(df_city_salary)

输出(按城市汇总,直观看到深圳薪资最高):

城市
北京 11333.333333
广州 9500.000000
上海 12000.000000
深圳 18000.000000
Name: 薪资, dtype: float64

示例 2:按「薪资等级」分组,统计每个等级的员工人数#

df_grade_count = df.groupby("薪资等级")["姓名"].count()
print("\n按薪资等级分组的员工人数:")
print(df_grade_count)

输出(高薪资等级有 4 人,中等级 2 人):

薪资等级
中 2
高 4
Name: 姓名, dtype: int64

2. 多聚合函数(agg)#

如果想对同一列同时执行多个聚合操作(比如既看均值,又看最大值),用 agg() 更高效。

示例:按「部门」分组,统计薪资的均值、最大值、总和#

df_dept_salary = df.groupby("部门")["薪资"].agg(["mean", "max", "sum"])
# 重命名列(更易读)
df_dept_salary.columns = ["薪资均值", "薪资最大值", "薪资总和"]
print("\n按部门分组的薪资统计:")
print(df_dept_salary)

输出(销售部均值略高,技术部总和更高):

薪资均值 薪资最大值 薪资总和
部门
技术部 11833.333333 18000 35500
销售部 12666.666667 15000 38000

3. 多列分组 + 多列聚合#

更复杂的场景:按「城市 + 部门」双维度分组,同时统计年龄和薪资。

df_city_dept = df.groupby(["城市", "部门"]).agg({
"年龄": "median", # 年龄取中位数
"薪资": "sum" # 薪资取总和
})
print("\n按城市+部门分组的统计:")
print(df_city_dept)

输出(精准定位 “北京 - 销售部” 的薪资总和、年龄中位数):

年龄 薪资
城市 部门
北京 技术部 20 8000
销售部 27.5 26000
广州 技术部 22 9500
上海 销售部 25 12000
深圳 技术部 30 18000

二、排序操作(Sort)#

排序分为「按值排序」(最常用)和「按索引排序」,核心是调整数据的展示顺序,让结果更易读。

1. 按值排序(sort_values)#

核心语法df.sort_values(by=列名, ascending=True/False, na_position="last")

  • by:指定排序的列(传列表可实现多列排序);
  • ascendingTrue= 升序(默认),False= 降序;
  • na_position:缺失值位置(last= 放最后,first= 放最前)。

示例 1:按「薪资」降序排序(从高到低)#

df_salary_desc = df.sort_values(by="薪资", ascending=False)
print("\n按薪资降序排序:")
print(df_salary_desc[["姓名", "城市", "薪资"]]) # 只展示关键列

输出(钱七薪资最高,张三最低):

姓名 城市 薪资
员工5 钱七 深圳 18000
员工4 赵六 北京 15000
员工2 李四 上海 12000
员工6 孙八 北京 11000
员工3 王五 广州 9500
员工1 张三 北京 8000

示例 2:多列排序(先按「城市」升序,再按「年龄」降序)#

df_multi_sort = df.sort_values(by=["城市", "年龄"], ascending=[True, False])
print("\n按城市升序、年龄降序排序:")
print(df_multi_sort[["姓名", "城市", "年龄", "薪资"]])

输出(同一城市内,年龄大的排前面):

姓名 城市 年龄 薪资
员工4 赵六 北京 28 15000
员工6 孙八 北京 27 11000
员工1 张三 北京 20 8000
员工3 王五 广州 22 9500
员工2 李四 上海 25 12000
员工5 钱七 深圳 30 18000

2. 按索引排序(sort_index)#

如果想按行索引(如 “员工 1”“员工 2”)排序,用 sort_index

df_index_sort = df.sort_index(ascending=False) # 索引降序(员工6→员工1)
print("\n按索引降序排序:")
print(df_index_sort[["姓名", "薪资"]])

输出:

姓名 薪资
员工6 孙八 11000
员工5 钱七 18000
员工4 赵六 15000
员工3 王五 9500
员工2 李四 12000
员工1 张三 8000

三、分组 + 排序 结合使用(实战常用)#

实际分析中,常先分组聚合,再对聚合结果排序,让统计结果更直观。

示例:按城市分组统计薪资均值,再按均值降序排序#

# 1. 分组聚合:按城市算薪资均值
df_city_salary = df.groupby("城市")["薪资"].mean()
# 2. 排序:按均值降序
df_city_salary_sorted = df_city_salary.sort_values(ascending=False)
print("\n按城市分组的薪资均值(降序):")
print(df_city_salary_sorted)

输出(快速看出深圳 > 上海 > 北京 > 广州的薪资水平):

城市
深圳 18000.000000
上海 12000.000000
北京 11333.333333
广州 9500.000000
Name: 薪资, dtype: float64

总结#

  1. 分组聚合:核心是「按类别汇总统计」,用 groupby() 指定分组列,配合 agg()/ 聚合函数(mean/count/max 等)实现单 / 多维度统计;
  2. 排序操作:按值排序用 sort_values()(指定by列,控制升 / 降序),按索引排序用 sort_index()
  3. 组合技巧:分组聚合后对结果排序,能快速突出核心结论(如哪个城市薪资最高、哪个部门人均薪资更高)。

文章目录

✨️ 复制成功,转载请标注本文地址