Python 玩转 Excel 案例【第 5 期】
大家好!今天我们来学习一个HR小伙伴经常遇到的场景:如何快速找出四个季度都上榜的优秀员工?
手动对比四个季度的名单,眼睛都快看花了,还容易漏掉。今天这个Python脚本,1秒钟帮你搞定!
一、案例背景
年底了,公司要评选全年优秀员工——条件很简单:四个季度都上榜的人。
打开Excel一看,四个季度的名单分别在B、C、D、E列:
你的任务:找出同时出现在这四列的人。
手动做法:复制→粘贴→去重→比对……四个季度比完,半小时过去了。
今天这个脚本:双击运行,3秒出结果!
二、整体功能预览
这个脚本主要完成以下任务:
三、准备工作
安装必要的库:
pip install pandas openpyxl
四、代码整体结构
import logging
from pathlib import Path
from typing import List, Optional, Union
import pandas as pd
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
# 核心函数
def process_employee_data(...): ...
def main():
"""主函数"""
success = process_employee_data("Chapter-5.xlsx")
print("处理成功" if success else "处理失败")
if __name__ == "__main__":
main()
五、核心函数详解
1. 函数定义与参数
def process_employee_data(
file_path: Union[str, Path],
source_sheet: str = "优秀员工名单表",
target_sheet: str = "全年优秀表",
quarter_cols: Optional[List[int]] = None
) -> bool:
参数说明:
- •
source_sheet:要读取的工作表名称(默认"优秀员工名单表") - •
target_sheet:要写入的工作表名称(默认"全年优秀表") - •
quarter_cols:四个季度的列索引(默认值是None)
返回值:布尔值,表示处理是否成功
2. 参数初始化
# 默认列索引(B-E列)
if quarter_cols is None:
quarter_cols = [1, 2, 3, 4]
file_path = Path(file_path)
知识点:
- •
Path(file_path):将字符串路径转为Path对象,方便路径操作 - •
quarter_cols 用 Optional 表示可以传None,内部再赋默认值(避免可变默认参数的问题)
3. 读取数据
# 1. 读取数据
logger.info(f"读取文件: {file_path}")
df = pd.read_excel(file_path, sheet_name=source_sheet)
if df.empty:
logger.error("数据为空")
return False
关键点:
- •
sheet_name=source_sheet:只读取指定的工作表
4. 提取各季度名单(核心处理)
# 2. 提取各季度名单(得到的是一个set集合的列表)
quarterly_sets = [
set(df.iloc[:, col].dropna().astype(str).str.strip())
for col in quarter_cols
if col < len(df.columns)
]
# 过滤空集合
quarterly_sets = [s for s in quarterly_sets if s]
逐层拆解:
df.iloc[:, col]:选取第col列的所有行
.dropna():删除空值(去除表格中的空白单元格)
.astype(str):转换为字符串类型(防止数字、日期等类型导致后续处理出错)
.str.strip():去除字符串两端的空格(清理数据中可能存在的多余空格)
set(...):转换为集合(自动去重,且支持高效的交集运算)
📝 .str 笔记
✅ 用 .str 的情况
想对这一列的每个元素做字符串操作时:
df['姓名'].str.strip() # 每个名字去空格
df['姓名'].str.upper() # 每个名字转大写
df['姓名'].str.contains('张') # 每个名字是否含'张'
❌ 不用 .str 的情况
df['姓名'].dropna() # 删除空行(操作整列,不是操作每个格子)
df['姓名'].unique() # 去重(操作整列)
df.shape # 操作整个表格
' 张三 '.strip() # 操作单个字符串
⚡️ 一句话记法
.str 就是说:"这一列的每一个元素,都给我..."
📝 列表推导式顺序
[表达式 for 变量 in 可迭代对象 if 条件]
# ③表达式 ①循环 ②过滤
执行顺序:①循环 → ②判断 → ③表达式
咱们的代码:
quarterly_sets = [
set(df.iloc[:, col]...) # ③符合条件的才执行这个
for col in quarter_cols # ①遍历每个季度
if col < len(df.columns) # ②只处理存在的列
]
等价于:
for col in quarter_cols: # ①先循环
if col < len(df.columns): # ②再判断
quarterly_sets.append(...) # ③最后执行
为什么if在后面? Python语法规定:列表推导式里,if必须跟在for后面
📝 过滤空集合
quarterly_sets = [s for s in quarterly_sets if s]
if s 的含义:
- • 空集合
set() 在Python中是 False
5. 计算交集(从最小的集合开始)
# 3. 计算交集(从最小的集合开始)
quarterly_sets.sort(key=len)
common = quarterly_sets[0].copy()
for s in quarterly_sets[1:]:
common &= s
if not common:
logger.info("无共同员工")
break
为什么要从最小的开始?
- •
sort(key=len):按集合大小排序,最小的在前
为什么要用 .copy()?
common = quarterly_sets[0].copy()
如果不copy,common和quarterly_sets[0]指向同一内存地址,操作common会直接修改原始数据。
用copy则新开一块内存,复制一份数据,保护原始集合不被修改。
交集运算
- •
common &= s:等价于 common = common & s - • 一旦交集为空,立即
break 跳出循环,提高效率
6. 保存结果
# 4. 保存结果
result_df = pd.DataFrame({
'序号': range(1, len(common) + 1),
'姓名': sorted(common)
}) if common else pd.DataFrame(columns=['序号', '姓名'])
with pd.ExcelWriter(file_path, engine='openpyxl', mode='a',
if_sheet_exists='replace') as writer:
result_df.to_excel(writer, sheet_name=target_sheet, index=False)
知识点:
- • 三元表达式:
A if condition else B,根据条件选择创建有数据的DataFrame或空DataFrame - • 字典创建DataFrame:键为列名,值为数据
- •
sorted(common):对姓名排序,使结果更整齐 - •
pd.ExcelWriter:高级Excel写入器 - •
mode='a':追加模式,不覆盖原文件的其他工作表 - •
if_sheet_exists='replace':如果目标工作表已存在,则替换
为什么用ExcelWriter而不是直接to_excel?
因为要在同一个文件中追加新工作表,而不是覆盖整个文件。
7. 异常处理
try:
# 主要逻辑...
return True
except Exception as e:
logger.error(f"处理失败: {e}")
return False
用try-except捕获可能的异常(如文件不存在、格式错误等),返回False表示失败。
六、运行效果展示
输入文件内容
优秀员工名单表:
运行程序
python 数据处理.py
控制台输出
2026-03-10 20:30:15 - INFO - 读取文件: Chapter-5.xlsx
2026-03-10 20:30:15 - INFO - 找到 6 名全年优秀员工
处理成功
输出结果
全年优秀表:
这6个人,就是四个季度全部上榜的优秀员工!
七、核心知识点总结
| | |
|---|
| pandas | read_excel() | |
| pandas | iloc[:, col] | |
| pandas | dropna() | |
| pandas | astype(str) | |
| pandas | str.strip() | |
| pandas | ExcelWriter | |
| Python | set | |
| Python | | |
| Python | &= | |
| Python | sorted() | |
| Python | .copy() | |
八、应用场景拓展
这个"交集计算"的思路可以广泛应用:
📦 资源获取提示
关注「码农自习室」,后台回复关键词 PythonExcel案例,即可获取本文完整代码及配套练习数据集,一起动手掌握高效数据操作的核心技巧!
❤️ 支持我们
如果本文对你有帮助,欢迎点赞 + 关注 + 点亮小红心,你的支持就是我们持续创作的最大动力~