使用re.search筛选CSV含关键词行丢失数据的技术求助
问题排查与代码修正
我帮你梳理下代码里的几个核心问题,这应该就是导致符合条件的行没被写入新文件的关键原因:
1. 行号对应关系完全混乱
你第一个循环里用next(csvreader)跳过了表头,所以enumerate(csvreader)返回的line是从0开始,对应原文件的第2行(索引1);但第二个循环里你从头读取整个文件,idx从0开始对应原文件的表头(索引0),还加了idx+=-1的操作,这会让idx变成-1、0、1...完全和之前记录的healthy_new里的行号对不上!比如第一个循环里匹配到的line=0是原文件的第1行(数据行第一行),但第二个循环里idx要等于1才对应这行,可你把idx减了1,自然匹配不到。
2. 不必要的异常捕获
ValueError在这里根本不会触发,re.search只会在正则表达式格式错误时报错,而你的关键词都是普通字符串,这个try-except不仅多余,还可能掩盖真正的错误(比如row[4]不存在导致的索引越界)。
3. 文件打开模式错误
在Python 3中处理CSV文件,应该用文本模式('r'/'w')而不是二进制模式('rb'),二进制模式可能会导致读取的内容编码异常,直接影响关键词匹配结果。
4. 冗余匹配影响效率
你的healthy_list里有重复的'diet',而且匹配到关键词后还继续循环其他关键词,既浪费性能又会重复添加行号(虽然最后转成集合去重,但完全没必要)。
修正后的代码
我直接重构了逻辑,避免行号匹配的问题,同时优化了匹配效率:
import csv import re # 先给关键词列表去重,避免重复匹配 healthy_list = list(set(['diet', 'low-fat', 'light', 'diet', 'salad', 'salads', 'baked', 'grilled', 'whole grain'])) # 预编译正则表达式,用|分隔关键词,自动忽略大小写,不用手动转lower() pattern = re.compile('|'.join(re.escape(word) for word in healthy_list), re.IGNORECASE) healthy_rows = [] # 用文本模式打开,指定newline=''避免换行符混乱,编码按需调整 with open("Data 2017.csv", "r", newline='', encoding='utf-8') as f: csvreader = csv.reader(f, delimiter=",") # 先保存表头,写入新文件时需要 header = next(csvreader) healthy_rows.append(header) # 直接遍历每一行,匹配到就加入结果列表,不用记录行号 for row in csvreader: # 先检查列数足够,避免索引越界 if len(row) >= 5: # 用预编译的正则快速匹配 if pattern.search(row[4]): healthy_rows.append(row) # 写入新文件,同样注意newline参数 with open("healthy_new_output.csv", "w", newline='', encoding='utf-8') as f: writer = csv.writer(f, delimiter=',') writer.writerows(healthy_rows)
关键改进点
- 直接保存符合条件的行,彻底规避行号对应错误的问题
- 预编译正则表达式,匹配效率更高,且自动忽略大小写
- 先检查行的列数,避免索引越界报错
- 用
with语句管理文件,自动关闭资源,避免泄漏 - 关键词列表去重,减少冗余匹配
内容的提问来源于stack exchange,提问作者sayalmondbutter
相关产品推荐
相关产品推荐

