首页 > 解决方案 > Pandas 上的模糊 Vlookup

问题描述

我有两个大约 300,000 行和大约 11 列的数据框。

第一个数据帧包含原始数据,其名称不是同质字符串。另一个有官方数据(和同质字符串)。首先,我尝试通过代码在“原始数据”和官方数据之间运行模糊匹配,这对于包含大约 200 个条目的数据框似乎效果很好。当我尝试在 >300,000 行上运行代码时,内核变慢(它已经运行了一个多小时)......关于如何加快这个过程的任何想法?我正在考虑将数据框拆分成更小的数据框,但我需要整个数据集来确保匹配正确。

谢谢!

PS当前代码:

def fuzzy_merge(df_1, df_2, key1, key2, threshold=90, limit=2):
    """
    :param df_1: the left table to join
    :param df_2: the right table to join
    :param key1: key column of the left table
    :param key2: key column of the right table
    :param threshold: how close the matches should be to return a match, based on Levenshtein distance
    :param limit: the amount of matches that will get returned, these are sorted high to low
    :return: dataframe with boths keys and matches
    """
    s = df_2[key2].tolist()

    m = df_1[key1].apply(lambda x: process.extract(x, s, limit=limit))    
    df_1['Example1'] = m

    m2 = df_1['CompanyName'].apply(lambda x: ', '.join([i[0] for i in x if i[1] >= threshold]))
    df_1['Example2'] = m2

    return df_1

from fuzzywuzzy import fuzz
from fuzzywuzzy import process

merged_df = fuzzy_merge(df1, df2, 'Example1', 'Example2', threshold=90)
print(merged_df)```

标签: pythonfuzzywuzzy

解决方案


鉴于您的任务,您将 300k 字符串与 300k 不同的字符串进行比较。您最终总共进行了 900 亿次比较,每次比较都使用模糊伍兹内的 levenshtein 距离,这是一个 O(N*M) 操作。这就是为什么这个操作永远不会很快。但是,可以通过一些更改更快地执行此匹配:

  1. 使用RapidFuzz而不是 FuzzyWuzzy,因为它实现了相同的算法,但要快得多

  2. RapidFuzz 允许将 a 传递score_cutoffprocess.extract. 这样,它只返回高于此分数的匹配项,并且通常可以非常快速地跳过错误匹配项

  3. s 中的字符串当前由 fuzz.extract 多次预处理。只执行一次会更快。

以下代码将这些更改应用于您的代码:

from rapidfuzz import process, utils as fuzz_utils

def fuzzy_merge(df_1, df_2, key1, key2, threshold=90, limit=2):
    s_mapping = {x: fuzz_utils.default_process(x) for x in df_2[key2]}

    m1 = df_1[key1].apply(lambda x: process.extract(
      fuzz_utils.default_process(x), s_mapping, limit=limit, score_cutoff=threshold, processor=None
    ))    
    df_1['CompanyName'] = m1

    m2 = df_1['CompanyName'].apply(lambda x: ', '.join(i[2] for i in x))
    df_1[key2] = m2

    return df_1

merged_df = fuzzy_merge(df1, df2, 'Example1', 'Example2', threshold=90)

这些更改使我的速度提高了大约 20 倍,但这取决于您的数据


推荐阅读