Python 玩转 Excel 案例【第 18 期】
📌 案例说明
原始数据表(员工信息表):
在日常数据分析中,我们经常需要按年龄段对员工进行分组统计,比如:20-25岁有多少人?26-30岁有多少人?
这是数据分析中非常常见的场景:将连续数值(年龄)离散化(分箱),然后统计各区间的人数。
目标任务:
在 Excel 中,这类需求通常使用 VLOOKUP + 辅助列,或者使用 FREQUENCY 数组函数,操作相对繁琐。
本期案例将跟大家一起学习如何用 Python 轻松实现数据分箱 + 分组统计。
核心操作:数据分箱 + 频次统计
- • 关键函数:
pd.cut()、value_counts()、sort_index() - • 核心逻辑:将年龄按区间分组,统计各年龄段人数,同时保留原始数据的分箱结果
📜 完整代码
"""
数据分箱 - 按年龄段分组统计
需求:将年龄按区间分组,统计各段人数
"""
import pandas as pd
# 读取数据
df = pd.read_excel("员工信息.xlsx")
# 定义年龄段区间和标签
bins = [20, 26, 31, 36, 100]
labels = ["20-25岁", "26-30岁", "31-35岁", "36岁及以上"]
# 在原表后面增加新列,写上所在的年龄段
df["年龄段"] = pd.cut(df["年龄"], bins=bins, labels=labels, right=False)
# 统计各年龄段人数
result = df["年龄段"].value_counts().sort_index()
# 保存到新文件
with pd.ExcelWriter("员工信息_统计.xlsx") as writer:
df.to_excel(writer, sheet_name="员工信息", index=False)
result.to_excel(writer, sheet_name="年龄段统计")
print("✅ 已完成:")
print(f"\n年龄段统计:")
print(result)
运行结果:
✅ 已完成:
年龄段统计:
年龄段
20-25岁 0
26-30岁 3
31-35岁 1
36岁及以上 4
Name: count, dtype: int64
输出文件(员工信息_统计.xlsx):
📑 Sheet1 - 员工信息(原表 + 年龄段列)
📑 Sheet2 - 年龄段统计(汇总结果)
第一步:导入所需库
import pandas as pd
代码解释:
- •
import pandas as pd
导入 pandas 库,这是 Python 数据处理的核心武器。它提供了 read_excel() 读取 Excel、DataFrame 数据结构、cut() 数据分箱、value_counts() 频次统计等强大功能。
第二步:读取数据
df = pd.read_excel("员工信息.xlsx")
代码解释:
- •
pd.read_excel()
读取 Excel 文件,返回 DataFrame(数据表格)对象。 - •
df
存储员工信息表,包含姓名、年龄、部门三列。
💡 小贴士:read_excel() 默认读取第一个工作表,如果文件有多个 Sheet,可以用 sheet_name 参数指定,如
pd.read_excel("文件.xlsx", sheet_name="Sheet2")
第三步:核心分箱操作
bins = [20, 26, 31, 36, 100]
labels = ["20-25岁", "26-30岁", "31-35岁", "36岁及以上"]
df["年龄段"] = pd.cut(df["年龄"], bins=bins, labels=labels, right=False)
这三行代码是整期案例的灵魂,实现了将连续年龄值划分到不同年龄段。我们来一步步拆解:
3.1 定义分箱边界 bins
bins = [20, 26, 31, 36, 100]
- • 含义:分成 4 个区间:
[20,26)、[26,31)、[31,36)、[36,100)
⚠️ 注意:左闭右开 [a, b) 是由 right=False 实现的,不是 pandas 默认行为。默认是左开右闭 (a, b]。
3.2 定义区间标签 labels
labels = ["20-25岁", "26-30岁", "31-35岁", "36岁及以上"]
- • 数量要求:
labels 的长度必须比 bins 少 1(4 个区间对应 5 个边界)
3.3 pd.cut() 执行分箱
df["年龄段"] = pd.cut(df["年龄"], bins=bins, labels=labels, right=False)
这是 pandas 中用于数据分箱的核心函数,将连续数值离散化。
- •
df["年龄"]:要分箱的数据列,本例为年龄列 - •
bins:分箱边界,本例为 [20,26,31,36,100] - •
labels:区间标签,本例为 ["20-25岁", "26-30岁", "31-35岁", "36岁及以上"] - •
right:区间是否右闭,本例为 False(左闭右开)
区间规则详解:
| | |
|---|
True | | (20,25], (25,30], (30,35] |
False | | [20,26), [26,31), [31,36) |
为什么选择 right=False?
- • 使用左闭右开
[20,26):20岁算"20-25岁",25岁算"20-25岁",26岁算"26-30岁" - • 符合人的直观理解:25岁属于20-25岁,26岁属于26-30岁
执行过程:
💡 小贴士:如果年龄出现 19 岁,会显示为 NaN(空值),因为不在任何区间内。可以根据实际情况调整 bins 的下限,比如改成 [0, 26, 31, 36, 100]。
第四步:统计各年龄段人数
result = df["年龄段"].value_counts().sort_index()
这行代码完成统计 + 排序,是数据分析中非常常用的组合操作。
4.1 .value_counts() - 统计频次
统计每个年龄段出现的次数(人数)。
执行结果:
26-30岁 3
31-35岁 1
36岁及以上 4
Name: count, dtype: int64
⚠️ 注意:20-25岁 没有出现,所以不会显示(0 值默认被省略)。
4.2 .sort_index() - 按标签排序
按年龄段标签排序,而不是按人数排序。
sort_index() 按标签排序:结果是按年龄段名称从小到大排列
26-30岁 3
31-35岁 1
36岁及以上 4
sort_values() 按人数排序:结果是按人数从少到多排列
31-35岁 1
26-30岁 3
36岁及以上 4
对比可见:
- • 需要按年龄段顺序看结果 → 用
sort_index() - • 需要找出人数最多/最少的年龄段 → 用
sort_values()
为什么用 sort_index()?
最终 result 内容:
年龄段
26-30岁 3
31-35岁 1
36岁及以上 4
Name: count, dtype: int64
第五步:保存结果
with pd.ExcelWriter("员工信息_统计.xlsx") as writer:
df.to_excel(writer, sheet_name="员工信息", index=False)
result.to_excel(writer, sheet_name="年龄段统计")
5.1 pd.ExcelWriter() - 创建 Excel 写入器
- • 作用:创建一个 Excel 文件写入对象,支持同时写入多个 Sheet
- •
with 语句:自动管理资源,写入完成后自动保存关闭
5.2 两个 to_excel() - 写入不同 Sheet
为什么一个加 index=False,一个不加?
- • df(DataFrame):是一个完整的二维表格,自带的行索引(0,1,2...)没有业务含义,保存到 Excel 时不需要显示
- • result(Series):索引就是"年龄段"标签,值就是"人数",两者都需要保留在 Excel 中
如果不加 index=False:
姓名 年龄 部门 年龄段
0 张三 28 销售部 26-30岁
1 李四 41 技术部 36岁及以上
...
多了一列无意义的数字序号。
如果给 result 加了 index=False:
3
1
4
只显示各个年龄段的人数,看不出哪个数字对应哪个年龄段,完全失去意义。
⚠️ 注意:必须指定不同的 sheet_name,否则后面的 Sheet 会覆盖前面的。
📚 本期核心知识点
📍 知识点 1:pd.cut() 数据分箱
pd.cut(df["年龄"], bins=[20,26,31,36,100], labels=["20-25岁", "26-30岁", "31-35岁", "36岁及以上"], right=False)
| | |
|---|
x | | |
bins | | [20,30,40] |
labels | | ["组1","组2"] |
right | | True |
include_lowest | | True |
其他用法示例:
# 等宽分箱(自动分成4组)
df["年龄分组"] = pd.cut(df["年龄"], bins=4)
# 只分箱不加标签(查看区间范围)
df["年龄区间"] = pd.cut(df["年龄"], bins=[20,30,40,100])
📍 知识点 2:value_counts() + sort_index() 统计排序
result = df["年龄段"].value_counts().sort_index()
| | |
|---|
value_counts() | | |
sort_index() | | |
sort_values() | | |
记忆口诀:统计次数找 value,排序方式看需求——标签排序用 index,数值排序用 values
📍 知识点 3:pd.ExcelWriter() 多 Sheet 保存
with pd.ExcelWriter("输出文件.xlsx") as writer:
df1.to_excel(writer, sheet_name="表1", index=False)
df2.to_excel(writer, sheet_name="表2")
| |
|---|
| 自动管理资源,不用手动 writer.save() |
| |
index | DataFrame 通常设为 False,Series 通常保留 |
📍 知识点 4:to_excel() 保存文件
df.to_excel("输出文件.xlsx", sheet_name="Sheet1", index=False)
| | |
|---|
excel_writer | | "文件.xlsx" |
sheet_name | | |
index | | True |
🔄 本案例核心流程
① 读取数据 → ② 定义分箱规则 → ③ cut 分箱 → ④ 统计人数 → ⑤ 保存到两个 Sheet
员工信息.xlsx
↓
pd.read_excel()
↓
df (DataFrame)
↓
pd.cut(年龄, bins, labels, right=False)
↓
df["年龄段"] = 分箱结果
↓
value_counts() + sort_index()
↓
result (统计结果)
↓
ExcelWriter (多Sheet保存)
↓
员工信息_统计.xlsx
├── Sheet1: 员工信息 (原表+年龄段列)
└── Sheet2: 年龄段统计 (汇总表)
📦 资源获取提示
关注「码农自习室」,后台回复关键词 PythonExcel案例,即可获取本文完整代码及配套练习数据集,一起动手掌握高效数据操作的核心技巧!
❤️ 支持我们
如果本文对你有帮助,欢迎点赞 + 关注 + 点亮小红心,你的支持就是我们持续创作的最大动力~