将以上文本处理方法组合成完整的数据处理流程,并掌握向量化、性能优化与最佳实践。


1. 综合实践案例

案例 1:用户信息清洗

import pandas as pd
import re
 
raw = pd.DataFrame({
    '原始信息': [
        '张三 | 138-0000-0000 | zhangsan@test.com | 北京',
        '李四 | 13911112222 | li@test.org | 上海',
        '王五 | 010-12345678 | wang@demo.net | 广州',
        None
    ]
})
 
# 1. 去除空行
df = raw.dropna().copy()
 
# 2. 拆分字段
split = df['原始信息'].str.split('|', expand=True)
df[['姓名', '电话', '邮箱', '城市']] = split
 
# 3. 清理各字段
df['姓名'] = df['姓名'].str.strip()
df['电话'] = df['电话'].str.strip().str.replace(r'[^0-9]', '', regex=True)
df['邮箱'] = df['邮箱'].str.strip().str.lower()
df['城市'] = df['城市'].str.strip()
 
# 4. 增加派生列
df['手机号'] = df['电话'].where(df['电话'].str.match(r'^1\d{10}$'))
df['邮箱有效'] = df['邮箱'].str.contains(r'@', regex=True, na=False)
 
# 5. 输出结果
print(df)

案例 2:日志解析

logs = pd.Series([
    '2024-01-01 10:00:00 INFO: 用户登录 user=1001',
    '2024-01-02 11:30:00 ERROR: 数据库连接失败 user=1002',
    '2024-01-03 09:15:00 INFO: 用户退出 user=1001'
])
 
# 提取时间、级别、消息、用户ID
parsed = logs.str.extract(
    r'(?P<时间>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s+'
    r'(?P<级别>\w+):\s+'
    r'(?P<消息>.*?)(?:\s+user=)?(?P<用户>\d+)?'
)
parsed['时间'] = pd.to_datetime(parsed['时间'])
 
print(parsed)

案例 3:文本分类特征

comments = pd.DataFrame({'评论': [
    '这个产品很好用', '服务太差了', '快递很慢',
    '质量不错,推荐', '再也不买了'
]})
 
# 情感词匹配
positive_words = ['好', '推荐', '不错']
negative_words = ['差', '慢', '再也不']
 
comments['积极'] = comments['评论'].apply(
    lambda x: any(w in str(x) for w in positive_words)
)
comments['消极'] = comments['评论'].apply(
    lambda x: any(w in str(x) for w in negative_words)
)
 
# 简单情感判断
def sentiment(text):
    if any(w in text for w in positive_words):
        return '正面'
    if any(w in text for w in negative_words):
        return '负面'
    return '中性'
 
comments['情感'] = comments['评论'].apply(sentiment)
print(comments)

2. 性能优化

2.1 优先使用向量化 .str 方法

低效方式高效方式
df['col'].apply(lambda x: x.lower())df['col'].str.lower()
df['col'].apply(lambda x: 'a' in x)df['col'].str.contains('a')
循环 + re.searchdf['col'].str.extract(r'...')
# 不推荐
df['小写'] = df['文本'].apply(lambda x: x.lower())
 
# 推荐
df['小写'] = df['文本'].str.lower()

原因

.str 方法在底层按列一次性执行,避免 Python 级循环与函数调用开销,性能可提升数倍到数十倍。

2.2 指定 regex 参数

# 不推荐:自动推断
df['文本'].str.replace('old', 'new')
 
# 推荐:显式指明
df['文本'].str.replace('old', 'new', regex=False)

显式指定 regex=False 可避免不必要的正则编译。

2.3 使用 string dtype

# 推荐:string 扩展类型拥有更一致的 API 行为
df['文本'] = df['文本'].astype('string')
 
# 加快大规模转换
df = df.convert_dtypes()

2.4 分段处理超大文本列

# 对超大列分块处理,避免内存峰值
result = pd.Series(index=df.index, dtype='string')
for start in range(0, len(df), 10000):
    chunk = df['文本'].iloc[start:start+10000]
    result.iloc[start:start+10000] = chunk.str.lower()

2.5 避免反复 apply

# 多次 apply 合并为一次
# 不推荐
df['a'] = df['文本'].apply(lambda x: x.strip())
df['b'] = df['文本'].apply(lambda x: x.upper())
 
# 推荐:一次处理
df[['a', 'b']] = df['文本'].apply(
    lambda x: pd.Series([x.strip(), x.upper()])
)

注意

若难以向量化,且文本长度较短、数据量不大,apply 也可接受。优先保证代码可读性。


3. 内存优化

3.1 转为 category

当字符串列取值有限且重复率高时,转为 category 可大幅节省内存:

df['城市'] = df['城市'].astype('category')
df['城市'].cat.categories

3.2 使用 string dtype

df['描述'] = df['描述'].astype('string')

3.3 检查内存占用

df['文本'].memory_usage(deep=True)
df.info(memory_usage='deep')

4. 最佳实践

实践说明
统一类型文本列统一为 string dtype
统一大小写尽早执行 str.lower() / str.strip()
缺失值策略明确 na=True/False/NaN 行为
使用命名正则组让提取结果列名清晰
分步验证每步 head() / sample() 检查
保留原始列新增清洗列而非覆盖原列,便于追溯
链式操作管道用 .pipe() 串联清洗步骤

链式管道示例

def clean_text(df):
    return (df
        .assign(
            姓名=df['姓名'].str.strip().str.title(),
            邮箱=df['邮箱'].str.strip().str.lower(),
            电话=df['电话'].str.replace(r'[^0-9]', '', regex=True)
        )
        .dropna(subset=['姓名', '邮箱'])
        .drop_duplicates(subset=['邮箱'])
    )
 
df_clean = df.pipe(clean_text)

5. 常见问题与排查

问题原因解决
AttributeError: Can only use .str accessor with string values列不是字符串astype('string')
匹配结果全为 False大小写或正则问题case=False 或检查正则
提取大量 NaN正则未匹配使用 extractall 或调整模式
替换未生效regex 未显式regex=True / regex=False
性能极慢大量 apply改用 .str 向量化

小结

  • 向量化优先:.str 替代 apply 和循环
  • 显式参数:regex= 指定正则行为
  • 类型优化:string dtype、category 降低内存
  • 流程规范:分步验证、保留原始列、管道化处理