Pandas读取多列.dat文件触发ParserError问题求助
解决pandas读取多列.dat文件触发的ParserError问题
作为Jupyter新手,你遇到的这个问题其实很常见——当数据文件列数变多后,pd.read_csv的空白分隔解析逻辑容易因为格式细节出问题。咱们一步步拆解原因和解决办法:
问题重现
你用CSV转成的.dat文件,4列时读取正常,列数增多就报错。你的核心代码和报错栈如下:
核心代码
import numpy as np import pandas as pd from scipy.optimize import curve_fit import matplotlib.pyplot as plt from matplotlib.ticker import MultipleLocator from matplotlib.colors import ListedColormap, LinearSegmentedColormap file1 = 'king2.dat' file2 = 'iso.dat' data1 = pd.read_csv(file1, delimiter='\s+', header=None, engine='python') data1.columns = ['no_plt', 'Op_RA_plt', 'Op_DE_plt', 'Vmag_plt', 'B- V_plt', '(B-V)o_plt', 'no_2_plt', 'FUV_mag_plt','FUV_magerr_plt', '(FUV-V)_plt', '(V-I)_plt', '(FUV-I)_plt', 'no_op_2M','Op_RA_2M','Op_DE_2M','Vmag_2M','(B-V)o_2M', 'FUV_mag_2M','FUV-V_2M','no_2M','j_m_2M','h_m_2M','k_m_2M','j-h_2M', 'h-k_2M','j-k_2M','(V-I)_2M','(FUV-I)_2M', 'no_MS','Op_RA_MS','Op_DE_MS','Vmag_MS','(B-V)o_MS', 'FUV_mag_MS','FUV-V_MS','(V-I)_MS','(FUV-I)_MS', 'no_508','Op_RA_508','Op_DE_508','Vmag_508','(B-V)o_508', 'FUV_mag_508','FUV-V_508', '(V-I)_508','(FUV-I)_508', 'no_RG','Op_RA_RG','Op_DE_RG','Vmag_RG','(B-V)o_RG','FUV_mag_RG', 'FUV-V_RG','(V-I)_RG','(FUV-I)_RG','no_RG609','Op_RA_RG609', 'Op_DE_RG609','Vmag_RG609','(B-V)o_RG609','FUV_mag_RG609', 'FUV-V_RG609', '(V-I)_RG609', '(FUV-I)_RG609', 'no_TF621','Op_RA_TF621','Op_DE_TF621','Vmag_TF621','(B-V)o_TF621', 'FUV_mag_TF621','FUV-V_TF621','(V-I)_TF621','(FUV-I)_TF621', 'no_onBSS','Op_RA_onBSS','Op_DE_onBSS','Vmag_onBSS','(B-V)o_onBSS', 'FUV_mag_onBSS','FUV-V_onBSS','(V-I)_onBSs','(FUV-I)_onBSS', 'no_BSSreg','Op_RA_BSSreg','Op_DE_BSSreg','Vmag_BSSreg', '(B-V)o_BSSreg','FUV_mag_BSSreg','FUV-V_BSSreg','(V-I)_BSSreg', '(FUV-I)_BSSreg','no_BSSreg558', 'Op_RA_BSSreg558' , 'Op_DE_BSSreg558','Vmag_BSSreg558','(B-V)o_BSSreg558', 'FUV_mag_BSSreg558','FUV-V_BSSreg558','(V-I)_BSSreg558','(FUV-I)_BSSreg558','no_aMS','Op_RA_aMS', 'Op_DE_aMS','Vmag_aMS','(B-V)o_aMS','FUV_mag_aMS','FUV-V_aMS','(V-I)_aMS','(FUV-I)_aMS','no_bMS', 'Op_RA_bMS','Op_DE_bMS','Vmag_bMS','(B-V)o_bMS','FUV_mag_bMS','FUV-V_bMS','(V-I)_bMS', '(FUV-I)_bMS','no _SED','Op_RA _SED','Op_DE _SED','Vmag _SED','(B-V)o _SED','FUV_mag _SED', 'FUV-V _SED','(V-I)_SED','(FUV-I)_SED'] data2 = pd.read_csv(file1, delimiter='\s+', header=None, engine='python') data2.columns =['age','log(Z)','mass','logl','logt','logg', 'FUVCa_14.76','NUVB15_14.76', '(FUV-NUV)14.76','V14.76','B14.76', 'B-V14.76','(FUV-V)14.76','(NUV-V)14.76','GA NUV14.76', '(Uf-Gn)14.76','I14.76','(V-I)14.76','(FUV-I)14.76'] def fit_data(): fig = plt.figure(1,figsize=(8,8)) plt.subplot(111) plt.scatter(data1['(B-V)o_plt'], data1['Vmag_plt'], marker='.', color='r', s=5) plt.scatter(data2['B-V14.76'], data2['V14.76'], marker='o', color='g', s=6) plt.xlabel('RA_F',size=20) plt.ylabel('DEC_F',size=20) plt.gca().invert_xaxis() plt.gca().invert_yaxis() plt.show() plt.close() fit_data()
报错栈
ParserError Traceback (most recent call last) <ipython-input-5-fe66f2a2aac9> in <module>() 13 data1.columns = ['age','FUVCa','NUVB15','(FUV-NUV)','V','B','B-V','(FUV-V)','(NUV-V)','I','(V-I)','(FUV-I)'] 14 ---> 15 data2 = pd.read_csv(file2, delimiter='\s+', header=None, engine='python') 16 data2.columns = ['no','Op_RA','Op_DE','Vmag','(B-V)o','FUV_mag','(FUV-V)','(V-I)','(FUV-I)', 'no_MS','Op_RA_MS','Op_DE_MS','Vmag_MS','(B-V)o_MS', 17 'FUV_mag_MS','FUV-V_MS','(V-I)_MS','(FUV-I)_MS','no_508','Op_RA_508','Op_DE_508','Vmag_508', ~/anaconda3/lib/python3.6/site-packages/pandas/io/parsers.py in parser_f(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, squeeze, prefix, mangle_dupe_cols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, dayfirst, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, escapechar, comment, encoding, dialect, tupleize_cols, error_bad_lines, warn_bad_lines, skipfooter, skip_footer, doublequote, delim_whitespace, as_recarray, compact_ints, use_unsigned, low_memory, buffer_lines, memory_map, float_precision) 707 skip_blank_lines=skip_blank_lines) 708 ---> 709 return _read(filepath_or_buffer, kwds) 710 711 parser_f.__name__ = name ~/anaconda3/lib/python3.6/site-packages/pandas/io/parsers.py in _read(filepath_or_buffer, kwds) 453 454 try: --> 455 data = parser.read(nrows) 456 finally: 457 parser.close() ~/anaconda3/lib/python3.6/site-packages/pandas/io/parsers.py in read(self, nrows) 1067 raise ValueError('skipfooter not supported for iteration') 1068 -> 1069 ret = self._engine.read(nrows) 1070 1071 if self.options.get('as_recarray'): ~/anaconda3/lib/python3.6/site-packages/pandas/io/parsers.py ...
问题原因分析
- 分隔符匹配不稳定:
delimiter='\s+'用来匹配任意数量的空白符,但当列数变多后,某行可能出现分隔符不一致(比如混合了空格和制表符,或者某列的值包含空格),导致解析时列数不匹配。 - 行格式不一致:大型数据文件容易存在异常行(比如空行、缺失部分列的行、格式错乱的行),列数少的时候可能刚好适配,列数多就暴露问题。
- Python引擎的解析限制:虽然指定了
engine='python',但它处理超大量列时的容错性不如C引擎(不过C引擎不支持skipfooter等部分参数)。
解决方案
1. 先排查并跳过异常行
先确认文件里是否有坏行,用error_bad_lines=False跳过解析失败的行,同时warn_bad_lines=True让pandas提示哪些行有问题,方便后续修复:
data1 = pd.read_csv(file1, delimiter='\s+', header=None, engine='python', error_bad_lines=False, warn_bad_lines=True)
2. 改用更稳健的空白分隔参数
试试用delim_whitespace=True代替delimiter='\s+',这个参数是pandas专门为空白分隔文件设计的,解析逻辑更稳定:
data1 = pd.read_csv(file1, delim_whitespace=True, header=None, engine='python')
3. 提前指定列数,确保匹配
你已经手动指定了列名,但要确保列名的数量和文件实际的列数完全一致。如果不确定,可以先读取少量行查看列数:
# 先读10行看列数 temp_data = pd.read_csv(file1, delimiter='\s+', header=None, engine='python', nrows=10) print(f"文件实际列数:{temp_data.shape[1]}") # 再调整你的列名列表数量,确保和实际列数一致
4. 用numpy读取后转DataFrame
如果pandas的解析还是有问题,可以先用numpy的loadtxt读取(它对格式的容忍度更高),再转成DataFrame:
import numpy as np # 读取数据,假设都是数值型,如果有字符串可以用dtype=object data_np = np.loadtxt(file1) data1 = pd.DataFrame(data_np) # 再设置列名 data1.columns = ['no_plt', 'Op_RA_plt', ...] # 你的完整列名列表
5. 检查数据文件的格式一致性
用命令行工具快速检查文件的行格式:
- 查看所有行的列数是否一致:
awk '{print NF}' king2.dat | sort -u(如果输出多个数字,说明有行列数不一致) - 查看前10行的格式:
head -10 king2.dat,确认分隔符是否统一
调试小技巧
- 先读取少量行测试,比如
nrows=50,快速验证解析逻辑是否正常 - 读取后打印前几行:
print(data1.head()),确认列是否正确分隔
内容的提问来源于stack exchange,提问作者BRMBU
相关产品推荐
相关产品推荐

