pandas中str.split()对none/nan返回nan而非空列表,因默认不处理缺失值;需先fillna('')再split,否则str[0]报错。

str.split() 为什么返回 NaN 而不是空列表
调用 str.split() 时,如果某行值为 None 或 NaN,结果直接是 NaN,不是空列表或空字符串。这是 Pandas 的默认行为——不尝试对缺失值做字符串操作。
- 必须先用
fillna('')或mask(df.col.isna(), '')填充,再 split;否则后续str[0]会报TypeError: string indices must be integers -
str.split(pat, n=1)比默认全切分快,尤其处理长文本时;n设太大会触发正则回溯,拖慢性能 - 若分隔符可能不存在(如日志中某些行没冒号),加
expand=False+str.get(0)比str[0]更安全,前者对空 list 返回None,后者直接报错
用 str.extract() 替代 findall 做命名分组提取
很多人习惯先 str.findall() 再转 DataFrame,但效率低、类型难控;str.extract() 是向量化命名提取的正确姿势,尤其适合结构化清洗(如从日志抽 IP、时间、状态码)。
- 正则必须带命名捕获组,例如
r'(?P<ip>\d+\.\d+\.\d+\.\d+):(?P<port>\d+)'</port></ip>,否则返回单列且列名是0 - 未匹配到的行,对应字段自动填
NaN,不用额外处理;但若想填空字符串,得链式调用.fillna('') - 避免写
.*?开头的贪婪模式,Pandas 正则引擎对超长文本容易卡住;优先锚定边界,比如用^和$或明确上下文字符
str.replace() 的正则陷阱:re.sub 默认不全局?
str.replace() 默认启用正则(当第一个参数是字符串且含元字符时),但它的行为和 re.sub() 不完全一致:它默认全局替换,无需 flags=re.G;真正容易出错的是转义和标志位传递。
- 要忽略大小写,必须显式传
regex=True, flags=re.I;只写flags=re.I但没写regex=True,会被静默忽略 - 替换内容里有
\1这类反向引用,必须确保原 pattern 是 raw string(r'(...)'}),否则\1被 Python 字符串解析成乱码 - 批量替换多个模式时,别堆砌多个
str.replace()链式调用——每调一次都遍历整列;改用str.replace(r'pattern1|pattern2', ...)合并,或预编译正则对象传入
str.contains() 返回布尔却常被误当索引用
str.contains() 返回 Series[bool],看着像能直接当布尔索引,但遇到 NaN 时默认返回 NaN,而布尔索引中 NaN 会被当作 False —— 导致漏掉本该匹配的行。
- 永远加
na=False参数,例如df.col.str.contains('error', na=False),否则NaN行永远进不了结果 - 搜索纯字符串(无正则元字符)时,显式加
regex=False,避免意外触发正则解析,速度也更快 - 若需“包含任意一个关键词”,别写
str.contains('a|b|c')—— 它等价于“包含 a 或 b 或 c 的子串”,不是“包含 a 或包含 b 或包含 c”;正确做法是用isin()配合str.split().explode(),或用apply(lambda x: any(k in x for k in keys))
pd.Series(['a', None]).str.contains('a'),很难记住它到底返回什么。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











