Skip to content

Pandas 字符串操作:向量化文本清洗

Updated on

文本列驱动搜索、分群和特征工程,但许多流水线仍然逐行循环或混用 None/NaN,导致筛选错误和代码缓慢。

  • 问题: 大小写、空白符和部分匹配混乱,使得 join 和分析结果不可靠。
  • 痛点: 按行的 Python 循环很慢,而不一致的缺失值(None vs NaN)会让比较逻辑失效。
  • 解决方案: 使用 pandas 的字符串 dtype,配合向量化 .str 方法、显式的正则控制,以及安全的 split / explode,让文本处理既快又可预测。

Want an AI agent that understands your pandas text cleaning and notebook context?

RunCell is a JupyterLab AI agent that can read your code, analyze DataFrames, understand notebook context, debug errors, and even generate & execute code for you. It works directly inside JupyterLab—no switching windows or copy-pasting.

👉 Try RunCell: runcell.dev (opens in a new tab)


快速参考

目标方法示例
规范大小写/空白符.str.casefold(), .str.strip()s.str.strip().str.casefold()
字面替换(快速).str.replace(..., regex=False)s.str.replace("-", " ", regex=False)
正则提取 / 查找.str.extract(), .str.contains()s.str.extract(r"(\d{4})")
拆分为多列.str.split(expand=True)s.str.split("/", expand=True, n=2)
拆分为多行.str.split().explode()df.assign(tag=df["tags"].str.split(",")).explode("tag")
长度/计数.str.len(), .str.count()s.str.count(r"\d")

从合适的字符串 dtype 开始

import pandas as pd
 
df["title"] = df["title"].astype("string[python]")
  • 使用 string dtype(或在安装 Arrow 时使用 "string[pyarrow]")会将缺失值统一为 <NA>,这与 .str 方法和比较运算更兼容。
  • 尽量避免混用 Python 对象;object 列在文本操作上更慢,也更不一致。

核心清洗模式

df["clean_name"] = (
    df["name"]
      .str.strip()
      .str.replace(r"\s+", " ", regex=True)
      .str.title()
)
  • 对于简单的字面替换,使用 regex=False,可以避免被当作正则解析,同时提升速度。
  • .str.normalize("NFKC") 可以统一 Unicode 变体,在处理用户输入匹配时很有用。

去噪与统一大小写

df["search_key"] = df["product"].str.casefold().str.replace("-", " ", regex=False)

casefoldlower 更适合国际化文本比较。


筛选与提取

# 精确的前缀/后缀检查
promo_rows = df[df["code"].str.startswith("PROMO", na=False)]
 
# 带 NA 安全处理的正则 contains
has_year = df["description"].str.contains(r"\b20\d{2}\b", regex=True, na=False)
 
# 捕获分组到列
df[["year", "country"]] = df["id"].str.extract(r"(?P<year>\d{4})-(?P<country>[A-Z]{2})")
  • 在过滤时设置 na=False,将缺失值视为“不匹配”,避免布尔索引崩溃。
  • extract 中使用命名分组,可以直接得到语义清晰的列名,无需额外重命名。

Split、Expand 和 Explode

# 拆分成多列
df[["city", "state"]] = df["location"].str.split(",", n=1, expand=True)
 
# 将类似列表的列拆分成多行
tags = df.assign(tag=df["tags"].str.split("|"))
tags = tags.explode("tag").assign(tag=lambda t: t["tag"].str.strip())
  • 使用 expand=True 保持列对齐;当单元格中包含多个 token 需要变为多行时,优先使用 explode
  • 在 join 或聚合之前,对拆出来的片段做清洗(str.strip, str.casefold)。

统计与度量文本

df["word_count"] = df["abstract"].str.split().str.len()
df["digit_count"] = df["code"].str.count(r"\d")
  • .str.len() 会正确处理 <NA>;当输入为 string dtype 时,结果为 Int64
  • 如果下游数值流水线需要普通整数,可以结合 fillna(0) 做填充。

性能与安全提示

  • 优先使用向量化的 .str 方法而不是 apply(lambda ...);前者更快且更好地处理 NA。
  • 仅需字面替换时显式指定 regex=False,减少正则开销并避免意外匹配。
  • 对于大文本列,可考虑使用 string[pyarrow] 以减少内存占用并加速常见操作(需要安装 pyarrow)。
  • 尽量只对关键字段做一次标准化(strip + casefold),然后复用这些规范化键来做 join 或去重,而不是多处重复计算。

向量化字符串操作能让文本清洗简洁且高效。可以将其与 pandas-data-cleaning 配合进行更广泛的数据质量检查,并在规范化键准备好之后,结合 pandas-merge-join 实现可靠的 join。