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

使用Python的fuzzywuzzy匹配两个数据集生成二进制标记

嘿,我懂你现在的困境——用双重循环处理5000行的df1和20万行的df2,那可是10亿次迭代,效率低到完全没法用。咱们换个高效的思路来解决这个相似地址匹配的问题,分几步来:

第一步:先做地址标准化

相似地址经常会因为大小写、标点、缩写(比如St/Street,Ave/Avenue)导致匹配失败,所以先统一格式是关键。你可以写个标准化函数:

import re

def standardize_address(address):
    # 转成小写,消除大小写差异
    address = address.lower()
    # 移除所有标点符号
    address = re.sub(r'[^\w\s]', '', address)
    # 替换常见的地址缩写(根据你的数据集调整缩写规则)
    address = re.sub(r'\bst\b', 'street', address)
    address = re.sub(r'\bave\b', 'avenue', address)
    address = re.sub(r'\blr\b', 'lane', address)
    # 去除多余的空格
    address = re.sub(r'\s+', ' ', address).strip()
    return address

# 给两个数据集添加标准化后的地址列
df1['standardized_address'] = df1['address'].apply(standardize_address)
df2['standardized_address'] = df2['address'].apply(standardize_address)
第二步:缩小匹配范围,减少计算量

直接全量匹配20万行太浪费资源,咱们先按city+state+postal_code分组,只在同一区域内找相似地址——毕竟跨城市的相似地址概率极低,这样能把匹配范围缩小N倍:

from collections import defaultdict

# 把df2按区域分组,存储每组的标准化地址列表
df2_region_groups = defaultdict(list)
for _, row in df2.iterrows():
    region_key = (row['city'], row['state'], row['postal_code'])
    df2_region_groups[region_key].append(row['standardized_address'])
第三步:用高效模糊匹配工具做相似性判断

推荐用rapidfuzz(比老牌的fuzzywuzzy快得多,适合大数据场景)来计算地址相似度,设定一个阈值(比如80分,你可以根据实际数据调整),超过阈值就算相似:

from rapidfuzz import process, fuzz

def check_similar_address(row):
    region_key = (row['city'], row['state'], row['postal_code'])
    # 如果当前区域在df2里没有数据,直接标记为0
    if region_key not in df2_region_groups:
        return 0
    # 在同区域的地址中找最高相似度得分
    highest_match_score = process.extractOne(
        row['standardized_address'],
        df2_region_groups[region_key],
        scorer=fuzz.token_set_ratio  # 这个评分器对语序不敏感,适合地址匹配
    )[1]
    # 超过阈值返回1,否则返回0
    return 1 if highest_match_score >= 80 else 0

# 给df1添加二进制标记列
df1['has_similar_address'] = df1.apply(check_similar_address, axis=1)
可选进阶方法:TF-IDF+余弦相似度

如果你的地址格式特别复杂,模糊匹配不够准确,可以试试用文本向量化的方法:

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

# 先训练TF-IDF模型,用所有标准化地址作为语料
all_standardized_addresses = pd.concat([df1['standardized_address'], df2['standardized_address']])
tfidf_vectorizer = TfidfVectorizer(ngram_range=(1, 2))  # 考虑1-2个词的组合,更贴合地址结构
tfidf_vectorizer.fit(all_standardized_addresses)

# 初始化标记列
df1['has_similar_address'] = 0

# 按区域分组处理
for region_key, df2_addresses in df2_region_groups.items():
    # 筛选df1中当前区域的行
    df1_region_mask = (df1['city'] == region_key[0]) & \
                      (df1['state'] == region_key[1]) & \
                      (df1['postal_code'] == region_key[2])
    if not df1_region_mask.any():
        continue
    # 提取当前区域的地址,转换成TF-IDF向量
    df1_region_addresses = df1.loc[df1_region_mask, 'standardized_address']
    df1_tfidf = tfidf_vectorizer.transform(df1_region_addresses)
    df2_tfidf = tfidf_vectorizer.transform(df2_addresses)
    # 计算余弦相似度矩阵
    similarity_matrix = cosine_similarity(df1_tfidf, df2_tfidf)
    # 找到每行的最大相似度,超过阈值(比如0.8)标记为1
    max_similarities = np.max(similarity_matrix, axis=1)
    df1.loc[df1_region_mask, 'has_similar_address'] = (max_similarities >= 0.8).astype(int)
一些注意事项
  • 阈值调整:不管用模糊匹配还是余弦相似度,都要根据你的实际数据测试阈值,找到准确率和召回率的平衡点
  • 缺失值处理:如果city/state/postal_code有缺失,你可以选择忽略这些字段分组,或者把缺失值归为同一组单独处理
  • 依赖安装:rapidfuzz需要单独安装,执行pip install rapidfuzz即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:15:07