使用Python删除Excel中的重复行
业务部的小谢离职,甩给接任者小李一个客户资料 Excel 文件,小李打开一看欲哭无泪,这个文件长达几万行,里面有大量的重复,如果不把重复行删除,以后可能一不小心就做了重复工作,比如短时间内重复给客户打去电话。为此,小李过来找我,希望我帮他写一个 Python 程序,用来删除 Excel 中的重复行。我照旧假装犹豫不决,说最近工作很忙,每天都要加班到晚上八九点云云。最后小李说请我吃一顿猪脚饭作为酬劳,我才假装勉为其难地答应了,哈哈哈,又骗到了一顿猪脚饭。
首先安装 openpyxl 库:
pip install openpyxl
一、删除完全重复行
如果 Excel 工作表中存在多个完全相同的行(所有对应单元格的值都相同),就将重复的行删除,只保留其中一行。
Python 程序:
from openpyxl import load_workbook
# 删除完全重复行,start 为起始行
def delete_repeat_rows(file_path,sheet_name,start=1):
# 加载 Excel 文件
workbook = load_workbook(file_path)
# 选择工作表
sheet = workbook[sheet_name]
i = sheet.max_row
while i >= start:
row1 = []
for k in range(sheet.max_column):
row1.append(sheet.cell(row=i,column=k+1).value)
j = i - 1
while j >= start:
row2 = []
for k in range(sheet.max_column):
row2.append(sheet.cell(row=j,column=k+1).value)
if row1 == row2:
print("删除:" + str(i))
sheet.delete_rows(i)
workbook.save(file_path)
j -= 1
i -= 1
# 设置文件名和工作表名,大小写敏感
file_path = '测试的文件.xlsx'
sheet_name = 'Sheet1'
# 起始行
start = 5
delete_repeat_rows(file_path,sheet_name,start)
在这段程序中,我们使用了两重 while 循环来遍历工作表,第一重 while 获取一个基准行 row1,行号为 i,第二重循环获取一个比较行 row2,行号为 j,如果 row1 等于 row2,则说明两行完全相同,删除行号为 j 的行。在这个过程中,我们使用 sheet.cell(row=i,column=k+1).value 获取单元格的值,并使用 row1.append() 函数将其追加到 row1 列表中(row2同理)。
在这里我们遍历行为什么使用 while 循环而不是 for 循环?为什么使用倒序遍历(递减循环)而不是顺序遍历?这是因为在 Excel 中删除行会导致后面的行号发生变化,总行数也会发生变化,对于循环次数不定甚至循环变量也不定的情况,最好是使用 while 循环,以免产生一些逻辑复杂的BUG,倒序遍历同理。
二、删除局部重复行
有时有一些行并不完全相同,但它们也是重复的数据,比如有两行客户资料,姓名和电话号码是相同的,但地址稍微有点不同,一行地址是以“广州市天河区”开头,另一行地址则是以“广州天河”开头,这种区别是没有意义的,这种情况也应该当成重复数据,我们只要确保姓名和电话号码不重复就行了。前面的程序并不能处理这种局部重复的情况,所以我又写了一段可用于删除局部重复行的程序。
Python 程序:
from openpyxl import load_workbook
# 删除局部重复行,cols 为限定要对比的列,start 为起始行
def delete_repeat_rows(file_path,sheet_name,cols,start=1):
# 加载 Excel 文件
workbook = load_workbook(file_path)
# 选择工作表
sheet = workbook[sheet_name]
i = sheet.max_row
while i >= start:
row1 = []
for col in cols:
row1.append(sheet[col + str(i)].value)
j = i - 1
while j >= start:
row2 = []
for col in cols:
row2.append(sheet[col + str(j)].value)
if row1 == row2:
print("删除第" + str(i) + "行")
sheet.delete_rows(i)
workbook.save(file_path)
j -= 1
i -= 1
# 设置文件名和工作表名,大小写敏感
file_path = '测试的文件.xlsx'
sheet_name = 'Sheet1'
# 限定要对比的列
cols = ['A','B','D']
# 起始行
start = 5
delete_repeat_rows(file_path,sheet_name,cols,start)
这段程序跟前面那段很相似,主要区别是它须指定需要对比的列,将列的字母序号组成列表 cols 传给自定义函数 delete_repeat_rows(),用循环 for col in cols 读出每列的字母序号 col,使用 sheet[col + str(i)].value 获取单元格的值。
至此,小李要的 Python 程序我就帮他写好了。