使用read_csv正则分隔符生成多余空列问题排查
问题分析:Pandas读取文本时出现多余NaN列的原因及解决办法
问题场景
需要读取如下格式的文本文件为Pandas DataFrame:
#Date run angle NAME #----- _______ ________ _______ 2023-02-15 10:00:00 120716 -1.75493 4.5x10-4 Al 40um 2023-02-15 10:38:48 120716 -1.75493 JD70-103 50um 0/90 deg 2023-02-15 18:25:41 120723 -0.658 JD70-103 50um 45/135 deg
尝试使用正则分隔符匹配空白但排除特定内容,代码如下:
df = pd.read_csv("file.txt", engine='python', sep='\s+(?!\d\d:\d\d:\d\d|Al|\d\dum|deg|((\d|\d\d|\d\d\d)\/(\d|\d\d|\d\d\d)))")
结果生成的DataFrame在目标列之间插入了多列NaN:
Date NaN None.1 None.2 run None.3 None.4 None.5 angle ... 0 2023-02-15 10:00:00 NaN NaN NaN 120716 NaN NaN NaN -1.75493 ... 1 2023-02-15 10:38:48 NaN NaN NaN 120716 NaN NaN NaN -1.75493 ... 2 2023-02-15 18:25:41 NaN NaN NaN 120723 NaN NaN NaN -0.658 ...
问题原因
你的正则分隔符逻辑存在两个核心问题:
- 负向预测断言的位置错误:你写的
\s+(?!...)是在匹配连续空白后,检查空白后面的内容是否不符合断言规则。但实际上,你需要的是不要把NAME列内部的空白当成分隔符,而你的断言逻辑完全搞反了——它会把大部分空白都当成分隔符,反而在不该分割的地方可能误判,同时连续空白会被拆分成多个匹配(Pandas的Python引擎处理正则分隔符时,会把每个匹配的分隔符都作为列分隔,导致连续空白之间产生空列,也就是NaN)。 - 文件是固定宽度格式,而非分隔符分隔:你的文件本质是**固定宽度(Fixed-Width)**文本,列与列之间通过固定空格数分隔,不是任意空白分隔。用正则分隔符处理这种格式本身就不合适,很容易因为空白数量变化导致分割错误。
正确解决方法
针对固定宽度格式的文件,Pandas专门提供了pd.read_fwf()方法,比正则分隔符更可靠:
方法1:直接使用read_fwf跳过注释行
import pandas as pd # 跳过前两行注释,指定列名 df = pd.read_fwf("file.txt", skiprows=2, names=["Date", "run", "angle", "NAME"])
方法2:用comment参数自动跳过注释行
df = pd.read_fwf("file.txt", comment="#", names=["Date", "run", "angle", "NAME"])
执行后得到的正确DataFrame如下:
Date run angle NAME 0 2023-02-15 10:00:00 120716 -1.75493 4.5x10-4 Al 40um 1 2023-02-15 10:38:48 120716 -1.75493 JD70-103 50um 0/90 deg 2 2023-02-15 18:25:41 120723 -0.65800 JD70-103 50um 45/135 deg
补充:坚持用正则分隔符的替代方案
如果一定要用read_csv+正则,可以匹配至少两个连续空白作为分隔符(NAME列内部是单个空白),以此区分列之间的分隔空白和列内部空白:
df = pd.read_csv("file.txt", engine='python', sep='\s{2,}', skiprows=2, names=["Date", "run", "angle", "NAME"])
内容的提问来源于stack exchange,提问作者bigboy1001
相关产品推荐
相关产品推荐

