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

基于Pandas处理含复杂条件的地点数据集去重问题

地点数据集去重解决方案

问题场景

我有一个大型地点数据集,需识别并删除重复记录,数据特点如下:

  • 存在明显重复:地址、名称、行政区完全一致的记录
  • 存在易混淆近似记录:同街道不同门牌号的记录(如80 cobbler road和88 cobbler road)为不同地点,需保留;而east street和2 east street属于同一地点的不同录入格式,需合并为一条
  • 多数记录缺失名称字段,仅能依靠地址和行政区字段判断
  • 行政区字段已完成格式简化,但地址处理需兼顾匹配同一地点和区分不同地点的需求

已完成的预处理代码

import pandas as pd
import numpy as np

addresses = ['regents street', '21 regent street',
             'bishopgate 3', '3 bishopgate', 'bishop gate', 'regent',
             'hill park', 'hill park road', '10 hill park road',
             '12 hill park', 'south street', 'south street', 'east street', '2 east street', 'cup street', 'bond street',
            '80 cobbler road', '88 cobbler road']

name = ['a','a','b','b','b','c','d','e','e','d', np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, 'g', 'h']
boroughs = ['royal borough of greenwhich', 'borough of greenwhich', 
            'royal borough of chelsea', 'chelsea', 'borough of chelsea',
            'greenwhich', 'haringey', 'haringey', 'borough of haringey', 'haringey',
           'southwark', 'southwark', 'hammersmith', 'borough of hammersmith', 
            'hackney', 'hackney', 'lambeth', 'lambeth']

df = pd.DataFrame({'address':addresses, 'name':name, 'borough':boroughs})

# 清洗行政区字段
df['borough_clean'] = df['borough'].str.replace('royal|royal borough of|borough of', '', regex=True).str.strip().str.lower()

完整去重实现方案

核心思路

生成标准化匹配键,区分两种场景:

  1. 同一地点的不同录入格式(如有无门牌号):通过行政区+标准化街道名匹配合并
  2. 同街道不同地点(如不同门牌号):保留带门牌号的不同记录,不合并

步骤1:地址标准化处理

提取门牌号,生成统一格式的街道名,解决地址语序、空格差异的匹配问题:

import re

def process_address(address):
    addr = address.lower()
    # 提取地址中的门牌号(取第一个连续数字)
    number_match = re.search(r'\d+', addr)
    number = number_match.group() if number_match else np.nan
    # 生成标准化街道名:去掉数字、合并空格、去除首尾空格
    street_clean = re.sub(r'\d+', '', addr).replace(' ', '').strip()
    return pd.Series([number, street_clean])

# 应用地址处理函数
df[['number', 'street_clean']] = df['address'].apply(process_address)

步骤2:分场景去重

2.1 处理有名称的记录

按名称+行政区+标准化街道名分组,每组保留一条记录(优先保留原始信息更完整的条目):

mask_has_name = df['name'].notna()
df_has_name_dedup = df[mask_has_name].groupby(['name', 'borough_clean', 'street_clean'], as_index=False).first()

2.2 处理无名称的记录

  • 同一街道组内优先保留带门牌号的记录(避免丢失具体位置信息)
  • 同街道不同门牌号的记录视为不同地点,全部保留
  • 无门牌号的重复记录直接去重
df_no_name = df[~mask_has_name].copy()

def dedup_no_name_group(group):
    if group['number'].notna().any():
        # 保留带门牌号的记录,去重重复门牌号
        return group[group['number'].notna()].drop_duplicates(subset=['number'], keep='first')
    else:
        # 无门牌号时直接去重地址
        return group.drop_duplicates(subset=['address'], keep='first')

df_no_name_dedup = df_no_name.groupby(['borough_clean', 'street_clean']).apply(dedup_no_name_group).reset_index(drop=True)

步骤3:合并结果

合并处理后的有名称和无名称数据,保留原始字段:

final_df = pd.concat([df_has_name_dedup, df_no_name_dedup], ignore_index=True)
# 保留原始字段(可根据需求调整)
final_df = final_df[['address', 'name', 'borough']]

验证效果

  • east street和2 east street合并为一条(保留带门牌号的记录)
  • south street的重复记录被删除
  • 80 cobbler road和88 cobbler road作为不同地点被保留
  • bishopgate 3、3 bishopgate、bishop gate因属于同一名称+行政区+标准化街道组,被合并为一条

内容的提问来源于stack exchange,提问作者Yolao_21

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 07:20:26