夜雨聆风学习资料网

ARTICLE · 1134732

Python语法日报 第14期|Excel自动化开篇——数据清洗实战.脏数据别扔,三下五除二给它洗干净

Python语法日报 第14期|Excel自动化开篇——数据清洗实战.脏数据别扔,三下五除二给它洗干净

上期把几十个Excel揉成一张总表了,看着挺爽。但打开一看,有的名字带空格,有的部门大小写乱写,有的工资是空的,还有重复的行。今天一起洗数据,把脏玩意儿整干净。

一、先看今天要洗啥

拿上期合并完的“汇总结果.xlsx”开刀,典型的脏数据长这样:

姓名
部门
工资
来源文件
张三
销售
8000
一部.xlsx
李四
技术部
12000
二部.xlsx
张三
销售
8000
一部.xlsx
王五
销售
三部.xlsx
赵六
技术
6800
二部.xlsx

毛病一堆:张三重复、部门名不统一、王五工资空的、名字前后有空格。一个一个手改?那不得改到后半夜。上代码。

二、去重——重复的行直接噶掉

from openpyxl import load_workbookwb = load_workbook('汇总结果.xlsx')ws = wb.activeseen = set()          # 记录见过的行rows_to_delete = []for row in range(2, ws.max_row + 1):# 把整行数据拼成个元组当指纹    key = (ws.cell(row, 1).value, ws.cell(row, 2).value, ws.cell(row, 3).value)if key in seen:        rows_to_delete.append(row)    # 重复的记下来else:        seen.add(key)# 倒着删,不然删一行行号全乱for row in reversed(rows_to_delete):    ws.delete_rows(row)wb.save('汇总结果_去重.xlsx')print(f'干掉{len(rows_to_delete)}行重复的')

关键点:删行必须倒着删。正着删的话,删完第3行,原来的第4行变成第3行,再删第4行就删错了。

三、填空——空的地方给它补上

空工资的填0,空部门的填“未知”。

wb = load_workbook('汇总结果_去重.xlsx')ws = wb.activefor row in range(2, ws.max_row + 1):# 部门空了填“未知”    dept = ws.cell(row, 2).valueif not dept or str(dept).strip() == '':        ws.cell(row, 2).value = '未知'# 工资空了填0    salary = ws.cell(row, 3).valueif not salary:        ws.cell(row, 3).value = 0wb.save('汇总结果_填空.xlsx')

坑:not dept能同时抓None和空字符串,但抓不了全是空格的" "。所以后面再加个str(dept).strip() == ''兜底。

四、去空格——名字前后别留白

wb = load_workbook('汇总结果_填空.xlsx')ws = wb.activefor row in range(2, ws.max_row + 1):for col in range(1, ws.max_column + 1):        cell = ws.cell(row, col)if isinstance(cell.value, str):            cell.value = cell.value.strip()   # 去掉前后空格wb.save('汇总结果_去空格.xlsx')

strip()把字符串前后的空格、换行、制表符全薅掉。中间的空格不动,别把“张 三”改成“张三”。

五、统一部门名——大小写和别名都归一

有的写“销售”,有的写“销售部”,有的写“销售部门”。全给它统一成“销售部”。

wb = load_workbook('汇总结果_去空格.xlsx')ws = wb.active# 别名映射表,左边是乱的,右边是标准的dept_map = {'销售': '销售部','销售部门': '销售部','技术': '技术部','技术部门': '技术部','行政': '行政部','行政部': '行政部'}for row in range(2, ws.max_row + 1):    dept = ws.cell(row, 2).valueif dept in dept_map:        ws.cell(row, 2).value = dept_map[dept]wb.save('汇总结果_统一部门.xlsx')

映射表想加就加,以后碰到新别名往里塞一行就行。

六、把上面几步串成一个清洗函数

from openpyxl import load_workbookdef clean_excel(input_file, output_file):    wb = load_workbook(input_file)    ws = wb.active# 1. 去重    seen = set()    del_rows = []for row in range(2, ws.max_row + 1):        key = (ws.cell(row,1).value, ws.cell(row,2).value, ws.cell(row,3).value)if key in seen:            del_rows.append(row)else:            seen.add(key)for row in reversed(del_rows):        ws.delete_rows(row)# 2. 去空格 + 填空 + 统一部门    dept_map = {'销售':'销售部', '技术':'技术部', '行政':'行政部'}for row in range(2, ws.max_row + 1):for col in range(1, ws.max_column + 1):            cell = ws.cell(row, col)if isinstance(cell.value, str):                cell.value = cell.value.strip()        dept = ws.cell(row, 2).valueif dept in dept_map:            ws.cell(row, 2).value = dept_map[dept]elif not dept:            ws.cell(row, 2).value = '未知'if not ws.cell(row, 3).value:            ws.cell(row, 3).value = 0    wb.save(output_file)print(f'清洗完毕:{output_file}')clean_excel('汇总结果.xlsx', '汇总结果_干净版.xlsx')

以后拿到脏数据,调这个函数就完事。

七、今儿个知识点

干啥
代码
去重
用set记录指纹,重复的记下来倒着删
填空
if not cell.value: cell.value = 默认值
去空格
cell.value.strip()
统一别名
字典映射,dept_map[旧值] = 新值
倒删行
for row in reversed(rows_to_delete): ws.delete_rows(row)

已更Excel系列:

第9期:库的选择与第一个读写

第10期:行列操作与遍历

第11期:单元格样式与公式

第12期:多sheet处理

第13期:批量合并多个文件

后台回复 001 ,直接拿Python全套学习资料、办公脚本、实战代码,拿走就能用。

相关学习资料

.00获取!小程序(我是下的APP)微店,搜酵道孝道生活馆点错APP,误入某保险,你有这样的经历吗?详细说说小学数学学好哪些就够了我做了一款用声音记录灵感的 App:星拾 Starift小学数学六年级上册《每日一练》30天,口算、简算、方程、应用题谁懂?小学语文阅读理解到底有多重要?AI+IP线上引流训练营