文本字段清洗:字符串、分类值与格式标准化

摘要

业务数据中大量字段都是文本,例如姓名、地区、渠道、订单状态、商品名称和备注。文本字段看似简单,却经常因为空格、大小写、别名、全角半角、非法字符和分类不统一,导致分组统计、筛选和匹配结果错误。

本文围绕 pandas 的字符串处理能力,介绍文本字段标准化、分类值映射、正则提取、非法值识别和清洗报告生成,帮助把混乱的文本字段整理为可分析、可复用的数据。

一、背景与问题

文本字段常见问题包括:

  • 同一地区出现 华东、华东 、East China。
  • 状态字段出现 Paid、paid、已支付、付款完成。
  • 商品名称中包含多余空格、换行符和特殊符号。
  • 手机号、订单号、门店编码格式不统一。
  • 人工填写的字段存在错别字和同义词。
  • 分类值数量膨胀,导致透视表和分组结果失真。

如果不处理这些问题,分组统计会变成:

text 复制代码
paid      100
Paid       32
已支付      8
付款完成     5

这些取值可能表示同一业务状态,却被当成不同类别。

文本清洗的目标不是"把字符串变好看",而是让文本字段具备稳定的业务含义。

二、核心概念

1. 字符串标准化

标准化是将不同写法统一为固定格式,例如:

  • 去除首尾空格。
  • 统一大小写。
  • 统一全角半角。
  • 去除多余换行和制表符。
  • 替换特殊符号。

标准化应尽量可解释,不要用过度复杂的规则误伤有效内容。

2. 分类值

分类值通常有有限取值集合,例如:

  • 订单状态:已支付、待支付、已取消、退款。
  • 地区:华东、华南、华北。
  • 渠道:官网、App、门店、第三方平台。

分类字段应该建立取值字典和映射规则。

3. 映射表

映射表用于把多个别名统一为标准值:

原始值 标准值
paid 已支付
Paid 已支付
付款完成 已支付
pending 待支付

映射表比散落在代码里的 if 判断更容易维护。

4. 正则表达式

正则适合处理格式化文本,例如提取编号、判断手机号、清理多余空白和识别特定模式。

正则很强大,但可读性较差。复杂规则应写注释并配套样例测试。

三、工作原理

1. 文本清洗流程

text 复制代码
读取原始文本
  → 转换为 string 类型
  → 基础标准化
  → 分类映射
  → 合法值检查
  → 无法识别值输出报告
  → 生成清洗字段

推荐保留原始列,并新增清洗后的标准列:

text 复制代码
status_raw     原始值
status_clean   标准值

2. 原始值与标准值

不要直接覆盖原始值。保留原始值有助于:

  • 追踪数据来源问题。
  • 优化映射表。
  • 审核清洗规则。
  • 处理争议记录。

3. 合法值校验

清洗后仍然需要检查是否存在未识别分类:

text 复制代码
标准值 ∈ 预定义枚举

未识别值不应该被悄悄归为"其他",除非业务明确允许。

四、实战示例

1. 准备示例数据

python 复制代码
import pandas as pd

df = pd.DataFrame(
    {
        "order_id": [" A001 ", "A-002", "A003\n", "a004"],
        "region": ["华东", "华东 ", "East China", "华南"],
        "status": ["Paid", "已支付", "付款完成", "pending"],
        "product": [" iPhone 15 ", "iPhone-15", "iphone 15", "苹果手机15"],
        "phone": ["138-0000-0000", "13800000001", " 13800000002 ", "invalid"],
    }
)

2. 转换为字符串类型

python 复制代码
text_columns = ["order_id", "region", "status", "product", "phone"]

for column in text_columns:
    df[column] = df[column].astype("string")

使用 pandas 的 string 类型可以更明确地处理缺失值和字符串方法。

3. 基础清洗

python 复制代码
def normalize_text(series: pd.Series) -> pd.Series:
    return (
        series.astype("string")
        .str.strip()
        .str.replace(r"\s+", " ", regex=True)
    )


df["order_id_clean"] = normalize_text(df["order_id"]).str.upper()
df["region_clean"] = normalize_text(df["region"])
df["status_clean"] = normalize_text(df["status"]).str.lower()
df["product_clean"] = normalize_text(df["product"]).str.lower()

\s+ 可以把多个连续空白字符替换为一个普通空格,包括换行和制表符。

4. 分类值映射

python 复制代码
status_mapping = {
    "paid": "已支付",
    "已支付": "已支付",
    "付款完成": "已支付",
    "pending": "待支付",
    "待支付": "待支付",
    "cancelled": "已取消",
    "已取消": "已取消",
}

df["status_standard"] = df["status_clean"].map(status_mapping)

映射失败的记录会得到缺失值,需要单独检查。

5. 地区映射

python 复制代码
region_mapping = {
    "华东": "华东",
    "east china": "华东",
    "华南": "华南",
    "south china": "华南",
}

df["region_standard"] = (
    df["region_clean"]
    .str.lower()
    .map(region_mapping)
)

如果映射表较大,可以把它维护在 Excel、CSV 或数据库中,由数据清洗程序读取。

6. 清洗手机号

python 复制代码
df["phone_clean"] = (
    df["phone"]
    .astype("string")
    .str.strip()
    .str.replace("-", "", regex=False)
    .str.replace(" ", "", regex=False)
)

df["phone_valid"] = df["phone_clean"].str.match(r"^1\d{10}$")
print(df[["phone", "phone_clean", "phone_valid"]])

手机号通常不应作为数值处理,否则可能丢失前导零或格式信息。

7. 提取订单编号

python 复制代码
df["order_number"] = (
    df["order_id_clean"]
    .str.extract(r"([A-Z]+[-]?\d+)", expand=False)
)

正则提取后要检查缺失结果,确认是否存在不符合格式的订单号。

8. 商品名称标准化

python 复制代码
product_mapping = {
    "iphone 15": "iPhone 15",
    "iphone-15": "iPhone 15",
    "苹果手机15": "iPhone 15",
}

df["product_standard"] = (
    df["product_clean"]
    .str.replace("-", " ", regex=False)
    .map(product_mapping)
)

商品名称标准化常常需要业务字典或商品主数据支持,不能完全依赖字符串规则。

9. 未识别值报告

python 复制代码
unknown_status = df.loc[
    df["status_standard"].isna(),
    ["order_id", "status", "status_clean"],
]

unknown_region = df.loc[
    df["region_standard"].isna(),
    ["order_id", "region", "region_clean"],
]

print(unknown_status)
print(unknown_region)

未识别值应进入人工复核或映射表维护流程。

10. 字段级清洗报告

python 复制代码
report = pd.DataFrame(
    [
        {
            "field": "status",
            "unknown_count": int(df["status_standard"].isna().sum()),
            "unique_raw": int(df["status"].nunique(dropna=True)),
            "unique_standard": int(df["status_standard"].nunique(dropna=True)),
        },
        {
            "field": "region",
            "unknown_count": int(df["region_standard"].isna().sum()),
            "unique_raw": int(df["region"].nunique(dropna=True)),
            "unique_standard": int(df["region_standard"].nunique(dropna=True)),
        },
    ]
)

print(report)

标准化后,唯一值数量通常会下降。如果下降过多,也可能说明规则过度合并。

五、常见问题与实践建议

1. 是否应该把所有文本都转小写?

不一定。状态、渠道等分类值可以统一大小写;姓名、品牌、产品型号等字段可能需要保留展示格式。可以使用一个字段做匹配,一个字段做展示。

2. 未识别值是否都归为"其他"?

不建议默认这样做。未识别值可能代表新业务类型或数据质量问题。可以先输出报告,确认后再决定是否归为"其他"。

3. 正则表达式越复杂越好吗?

不是。复杂正则很难维护,应优先使用简单、可解释的规则。复杂规则需要样例测试和注释。

4. 如何管理映射表?

小项目可以使用字典;稳定项目建议使用 CSV、Excel、数据库表或配置文件,并记录版本、维护人和更新时间。

5. 文本清洗会不会误伤数据?

会。比如去除所有空格可能让产品型号或地址失真。因此每条规则都要结合字段语义设计。

六、进阶思考

1. 建立标准字典

文本标准化的长期方案是建立主数据或标准字典,例如:

  • 地区字典。
  • 商品字典。
  • 渠道字典。
  • 状态枚举。
  • 组织机构字典。

清洗程序应尽量引用标准字典,而不是在代码中堆规则。

2. 模糊匹配

当文本存在错别字或相似名称时,可以使用模糊匹配辅助人工修正。但模糊匹配不应自动覆盖高风险字段,应输出候选项和置信度。

3. 清洗规则测试

为映射规则准备测试样例:

python 复制代码
def test_status_mapping() -> None:
    source = pd.Series(["Paid", "已支付", "付款完成"])
    result = source.astype("string").str.strip().str.lower().map(status_mapping)
    assert result.tolist() == ["已支付", "已支付", "已支付"]

规则变化后,测试可以避免旧数据被错误处理。

4. 从字段清洗到数据治理

如果同一个字段在多个系统中长期不一致,单靠分析端清洗无法根治。应推动数据源系统统一字段规范和枚举约束。

结论

文本字段清洗的核心是标准化、映射和校验。pandas 的字符串方法可以处理空格、大小写、替换和正则提取,映射表可以把别名统一为标准分类,清洗报告可以帮助持续优化规则。

下一篇将进入数据筛选与排序,学习如何构建可靠的数据子集,并为后续分组统计和业务分析准备干净的数据范围。

参考资料

  1. pandas 字符串方法:https://pandas.pydata.org/docs/user_guide/text.html
  2. pandas Series.str 文档:https://pandas.pydata.org/docs/reference/series.html#string-handling
  3. Python re 文档:https://docs.python.org/3/library/re.html
相关推荐
ManageEngineITSM11 小时前
工单分类怎么设计?类别、子类别与自动分派的实用方法
大数据·服务器·数据库·人工智能·分类·数据挖掘
字节跳动数据平台11 小时前
让企业本体真正运转起来:火山引擎知识引擎VeKnow 的三层重构与业务实践
大数据
听我哔哔11 小时前
口播视频唇形总对不上,Seedance 2.5在zeekeAI里同步
人工智能·音视频
Raas10011 小时前
MAI Gateway实战部署:AI网关私有化部署?从0到1上手指南
人工智能·gateway·mai gateway·企业级ai产品
专注仿真11 小时前
卷积神经网络(CNN)算法详解
人工智能·python·算法·代码·大模型训练
FII工业富联科技服务12 小时前
多智能体如何进入制造现场?从业务协同到数字孪生验证
大数据·人工智能·算法·机器人·制造·数字孪生
golang学习记12 小时前
IDEA 开始换芯,发布全新AI版终端
java·人工智能·intellij-idea
武子康12 小时前
给游戏 Agent 接口时,隐藏答案会从哪条路漏出去?
人工智能
指针向南12 小时前
批量压缩视频有文件没变小?HandBrake等3款对比
图像处理·人工智能·计算机视觉·音视频
Whoami!12 小时前
F-《AI接口协议:API调模型、MCP接工具、A2A连Agent》
人工智能·mcp·a2a·ai协议