行数不一致主因是隐藏字符或字段内换行未引号包裹,应先用cat -A或PowerShell查原始字节,再针对性调整lineterminator、quoting或on_bad_lines参数。
导入后 len(df) 和原始文件行数对不上,先查隐藏字符
excel 或 csv 里肉眼看不见的换行符、零宽空格、bom 头,会让 pandas 误判行边界,尤其在 windows 编辑器里保存的文件容易带 \r\n 混用或 \ufeff。别急着调参数,先看原始文件真实结构。
- 用命令行快速检查:
head -n 5 file.csv | cat -A(Linux/macOS)或Get-Content file.csv -Encoding UTF8 | Select-Object -First 5 | ForEach-Object { $_.ToString().ToCharArray() | ForEach-Object { "{0:X4}" -f [int]$_ } -join ' ' }(PowerShell) - 重点看是否有
^M(\r)、EF BB BF(BOM)、200B(零宽空格) - pandas 默认用
\n分行,遇到孤立\r或嵌入式换行(如字段内"abc\ndef")会多切一行
pd.read_csv 中哪些参数真正影响行数统计
不是所有参数都管“读进来几行”,关键只在三处:分隔逻辑、引号处理、错误容忍。其他像 dtype 或 usecols 不改变行数,只改内容。
-
lineterminator:强制指定换行符,比如设为'\n'可绕过混用\r\n导致的误切 -
quoting和quotechar:若字段含换行但没被引号包裹,pandas 会提前断行;设quoting=csv.QUOTE_ALL或检查原始导出是否漏引号 -
on_bad_lines='skip'(pandas ≥1.3):跳过格式错乱行,但会静默丢数据;on_bad_lines='warn'能看到具体哪几行被跳了 - 避免用
error_bad_lines=False(已弃用),它不报错也不提示,容易漏掉问题行
怎么确认到底丢了哪几行或多了哪几行
靠 len(df) 对比太粗糙,得定位到具体行为什么异常。核心是让 pandas “吐出”它认为的每一行原始文本。
- 加
keep_default_na=False, skip_blank_lines=False,再用df.iloc[:10].to_string()看前几行是否包含意外换行 - 用
pd.read_csv(..., nrows=100, header=None)不带列名读,把每行当纯字符串,再print(repr(row[0]))查看原始字节表现 - 如果源是 Excel,别用
read_csv去读.xlsx—— 改用pd.read_excel,否则 openpyxl 引擎可能把合并单元格、注释行也当数据行算进去 - 导出时用
df.to_csv(..., line_terminator='\n')统一换行符,避免下次再踩坑
跳过错误记录时,on_bad_lines='skip' 的副作用
它确实能防止报错中断,但代价是:丢失行不标记、不返回索引、不保证顺序连续。你拿到的 df.index 看似从 0 开始,实际可能缺了第 17 行、第 203 行……而你完全不知道。
- 必须配合日志:用
warnings.catch_warnings(record=True)捕获UserWarning,里面含被跳行号 - 更稳妥的做法是先用
on_bad_lines='warn'运行一次,记下警告里的行号,再人工检查对应原始行 - 如果错误行有规律(比如总在含 emoji 的字段),不如预处理:用 Python 逐行读文件,
line.encode('utf-8', errors='ignore').decode('utf-8')清掉非法字节,再喂给read_csv
chunksize 或写自定义 parser,先用 cat -A 或十六进制查看器看前三行原始字节。

















