You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用正则捕获重音字符,去除数据集列含复数、拼写错误的重复项

问题诊断与优化方案

你的代码没能达到预期去重效果,核心问题如下:

  • 未处理重音字符:带重音和无重音的同一名称被判定为不同项,比如maisonduesiècle和maisonduesiecle无法被识别为重复
  • 单复数逻辑单向:仅检查当前名称加s是否在列表中,若先出现单数、后出现复数,复数会被误判为新项(比如先有maison,后来的maisons会被错误加入)
  • 列表查询效率低:用列表in操作判断存在性,数据量大时速度慢且逻辑易出错
  • 拼写错误处理不全:仅移除了非字母字符,但未覆盖字母错位类错误

优化步骤与代码

1. 处理重音字符

通过Unicode标准化将带重音的字符转换为普通字母,这是解决重音导致重复的关键:

import unicodedata

def remove_accents(text):
    return unicodedata.normalize('NFKD', text).encode('ascii', 'ignore').decode('utf-8')

2. 标准化文本格式

统一转小写、过滤非字母字符,确保不同格式的同一名称能被归一化:

import pandas as pd

def normalize_name(text):
    if pd.isna(text):
        return ''
    # 移除重音
    text_no_accents = remove_accents(text)
    # 仅保留字母并转小写
    normalized = ''.join([c.lower() for c in text_no_accents if c.isalpha()])
    return normalized

3. 完善单复数去重逻辑

改用集合存储已处理名称(查询效率O(1)),同时覆盖单数转复数、复数转单数的双向检查,还兼容法语部分特殊复数规则:

# 读取数据集
monuments = pd.read_csv("data/liste-des-immeubles-proteges-au-titre-des-monuments-historiques.csv", sep=";")   
# 生成标准化后的名称列
monuments['normalized_tico'] = monuments['tico'].apply(normalize_name)

unique_names = set()
sieve = []

for name in monuments['normalized_tico']:
    if not name:
        continue
    exists = False
    # 检查当前名称或其复数形式是否已存在
    if name in unique_names or (name + 's') in unique_names:
        exists = True
    # 若当前是复数(结尾为s),检查对应单数是否已存在
    elif name.endswith('s'):
        singular = name[:-1]
        if singular in unique_names:
            exists = True
    # 处理法语中以x结尾的复数(如château -> châteaux)
    elif name.endswith('x'):
        singular_candidate = name[:-1]
        if singular_candidate in unique_names or (singular_candidate + 's') in unique_names:
            exists = True
    
    if not exists:
        unique_names.add(name)
        sieve.append(name)

print(len(sieve))

4. 额外处理拼写错误

如果要处理字母错位类错误(比如maison和maosn),可以用fuzzywuzzy库计算编辑距离判断名称相似度:

from fuzzywuzzy import fuzz

def is_similar(name, unique_set, threshold=90):
    for existing in unique_set:
        if fuzz.ratio(name, existing) >= threshold:
            return True
    return False

将该函数加入循环的exists判断即可,注意这会增加运行时间,适合中等规模数据集。

内容的提问来源于stack exchange,提问作者Mustapha Unubi Momoh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 17:40:31