如何解决pandas read_csv读取含tuple字段的CSV解析错误?
解决Pandas加载含Tuple字段的CSV文件解析错误
问题场景
我有一个格式不规范的CSV文件,尝试用Pandas的read_csv函数加载时遇到了解析错误。
CSV文件内容(test.csv)
feature_idx,cv_scores,avg_score,total-features (4,),[0.71657 0.75430665 0.77866281 0.85293036 0.76370522],0.773235007449579,80 (4, 15),[0.79150981 0.82751849 0.83777517 0.9246948 0.82462535],0.8412247254527763,80 (1, 4, 15),[0.82173419 0.85052599 0.86065046 0.93704226 0.84315839],0.862622256166522,80 (1, 4, 15, 70),[0.82448556 0.86513518 0.87640778 0.93881338 0.84777784],0.8705239466728865,80
加载错误信息
执行以下代码:
pandas.read_csv('test.csv')
抛出解析错误:
pandas.errors.ParserError: Error tokenizing data. C error: Expected 5 fields in line 4, saw 6
原因是第一个字段的Tuple格式(如(1, 4, 15))里的逗号被Pandas当成了字段分隔符,导致每行识别的字段数不一致。
无效尝试
我尝试过用converters参数指定自定义解析函数,但错误依旧:
df = pd.read_csv('test.csv', converters={'feature_idx': parse_tuple}) # parse_tuple为自定义Tuple解析函数
错误信息:
pandas.errors.ParserError: Error tokenizing data. C error: Expected 5 fields in line 4, saw 6
当前使用的Pandas版本:1.5.3
解决方案
问题核心是:Pandas的默认C解析器会先拆分字段,再应用converters,所以转换器无法解决字段数不匹配的问题。需要先让解析器正确识别字段边界,再处理类型转换。
方法1:使用Python引擎+正则分隔符
Python引擎支持正则表达式作为分隔符,可以匹配不在括号/方括号内的逗号作为字段分隔符,避免拆分Tuple或列表内部的逗号:
import pandas as pd import re # 正则规则:匹配不在()或[]范围内的逗号 sep_regex = re.compile(r',(?![^()]*\))(?![^\[\]]*\])') # 加载CSV,指定分隔符和引擎 df = pd.read_csv('test.csv', sep=sep_regex, engine='python')
方法2:手动读取并拆分每行
逐行读取文件,手动拆分每个字段,完全控制解析逻辑:
import pandas as pd data_rows = [] # 读取文件 with open('test.csv', 'r', encoding='utf-8') as f: # 获取表头 header = f.readline().strip().split(',') # 处理每一行数据 for line in f: line = line.strip() # 先按"],"拆分,分离出列表部分和后续字段 split_after_list = line.split('],') # 拆分feature_idx和cv_scores feature_part, cv_part = split_after_list[0].split(',[', 1) feature_idx = feature_part.strip() cv_scores = f'[{cv_part.strip()}]' # 拆分剩余的avg_score和total-features avg_score, total_features = split_after_list[1].split(',', 1) # 添加到数据列表 data_rows.append([feature_idx, cv_scores, avg_score.strip(), total_features.strip()]) # 转为DataFrame df = pd.DataFrame(data_rows, columns=header)
方法3:转换字段为实际类型
加载完成后,用ast.literal_eval将字符串形式的Tuple和列表转为实际Python对象:
import ast # 转换feature_idx为Tuple df['feature_idx'] = df['feature_idx'].apply(ast.literal_eval) # 转换cv_scores为列表 df['cv_scores'] = df['cv_scores'].apply(ast.literal_eval)
内容的提问来源于stack exchange,提问作者Amina Umar
相关产品推荐
相关产品推荐

