pandas读取CSV时过滤缺失闭合结束引号坏行的方法
问题场景
使用pandas.read_csv读取|为分隔符、双引号为引用符的CSV文件时,如果存在双引号未闭合的行,会直接抛出报错:ParserError: Error tokenizing data. C error: EOF inside string starting at row 2,无法直接完成读取。需求是将这类引号不闭合的坏行单独拆分到独立DataFrame,仅对格式合法的行做后续解析处理。
本次测试的示例文件
bad_data.txt内容如下:LOC_ID|LOC_ID_NEW|LOCATION_ADDRESS 30000022||20000022|"2027TH 28TH AVE. N| APT Z11" 30000023||20000023|"24290 MND STREET, APT.其中第三行(第二条数据)的地址字段仅包含起始双引号、缺失闭合双引号,属于需要过滤的坏行。
实现思路
pandas默认的C解析引擎遇到未闭合引号时,会默认将后续行判定为当前引号字段的内容,哪怕设置on_bad_lines='skip'也无法识别这类错误,会直接终止解析。最可靠的方案是先在文本层做逐行校验:
- 逐行读取文件内容,先单独提取表头
- 对每一条数据行统计非转义双引号的数量:数量为偶数代表引号完全闭合,属于合法行;数量为奇数代表存在未闭合引号,属于坏行
- 拼接所有合法行,通过
StringIO传给pandas.read_csv正常解析得到合法数据DataFrame - 所有筛选出的坏行单独存储为坏数据DataFrame,可按需保留原始内容或做字段切分
参考代码
import pandas as pd from io import StringIO # 读取参数和原逻辑保持一致即可 FILE_PATH = 'c:\\bad_data.txt' SEP = '|' QUOTE_CHAR = '"' ENCODING = 'utf-8' # 如果文件是gbk编码自行修改此处 valid_lines = [] bad_lines = [] with open(FILE_PATH, 'r', encoding=ENCODING) as f: # 提取表头,归入合法行集合 header = f.readline() valid_lines.append(header) # 逐行校验数据 for raw_line in f: # 统计引号数,偶数为合法、奇数为未闭合 quote_cnt = raw_line.count(QUOTE_CHAR) if quote_cnt % 2 == 0: valid_lines.append(raw_line) else: # 去掉行尾换行符后存入坏行集合 bad_lines.append(raw_line.rstrip('\r\n')) # 解析合法数据 valid_df = pd.read_csv( StringIO(''.join(valid_lines)), sep=SEP, quotechar=QUOTE_CHAR ) # 构造坏数据DataFrame,如需拆分字段可对raw_bad_line做split(SEP)处理 bad_df = pd.DataFrame({'raw_bad_line': bad_lines}) # 后续可分别对两个DataFrame做处理 print("=== 合法数据预览 ===") print(valid_df) print("\n=== 坏数据预览 ===") print(bad_df)
运行结果
针对示例数据的运行输出如下:
=== 合法数据预览 === LOC_ID LOC_ID_NEW LOCATION_ADDRESS 0 30000022 NaN 2027TH 28TH AVE. N| APT Z11 === 坏数据预览 === raw_bad_line 0 30000023||20000023|"24290 MND STREET, APT.
补充说明
- 如果数据中存在
\"形式的转义双引号,只需要修改引号计数逻辑,排除前置反斜杠的转义引号后再统计奇偶即可 - 若坏行需要和合法表保持同字段结构,直接对坏行原始字符串用
split(SEP)切分后传入DataFrame即可,不需要走CSV引用解析逻辑
内容的提问来源于stack exchange,提问作者Yuva
相关产品推荐
相关产品推荐

