【问题标题】:What is the most efficient way to dedupe a Pandas dataframe that has typos?对有拼写错误的 Pandas 数据框进行重复数据删除的最有效方法是什么?
【发布时间】:2018-01-01 23:04:29
【问题描述】:

我有一个需要重复数据删除的姓名和地址数据框。问题是其中一些字段可能有拼写错误,即使它们仍然是重复的。例如,假设我有这个数据框:

  index  name          zipcode
-------  ----------  ---------
      0  john doe        12345
      1  jane smith      54321
      2  john dooe       12345
      3  jane smtih      54321

拼写错误可能出现在姓名或邮政编码中,但让我们担心这个问题的姓名 one。显然 0 和 2 和 1 和 3 一样是重复的。但是计算上最有效的方法是什么?

我一直在使用 Levenshtein 距离来计算来自 fuzzywuzzy package 的两个字符串之间的距离,这在数据框很小的情况下效果很好,我可以通过以下方式遍历它:

from fuzzywuzzy import fuzz

for index, row in df.iterrows():
    for index2, row2 in df.iterrows():
        ratio = fuzz.partial_ratio(row['name'], row2['name'])

        if ratio > 90:  # A good threshold for single character typos on names
            # Do something to declare a match and throw out the duplicate

显然,这不是一种可以很好扩展的方法,不幸的是,我需要对大约 7M 行长的数据帧进行重复数据删除。显然,如果我还需要对邮政编码中的潜在拼写错误进行重复数据删除,情况会变得更糟。是的,我可以使用 .itertuples() 来做到这一点,这将使我的速度提高约 100 倍,但我是否错过了比这个笨重的 O(n^2) 解决方案更明显的东西?

有没有更有效的方法可以对这些嘈杂的数据进行重复数据删除?我已经查看了dedupe package,但这需要标记数据用于监督学习,我没有也没有印象,这个包将处理无监督学习。我可以推出自己的无监督文本聚类算法,但如果有现有的更好的方法,我宁愿不必走那么远。

【问题讨论】:

  • dedupe包会帮你做一些带标签的数据(我是这个包的作者)

标签: python pandas nlp python-dedupe


【解决方案1】:

pandas-dedupe 包可以帮助您完成任务。

pandas-dedupe 的工作原理如下:首先它要求您标记一堆他最困惑的记录。之后,他使用这些知识来解决重复实体。就是这样:)

您可以尝试以下方法:

import pandas as pd
from pandas_dedupe import dedupe_dataframe

df = pd.DataFrame.from_dict({'name':['john', 'mark', 'frank', 'jon', 'john'], 'zip':['11', '22', '33', '11', '11']})

dd = dedupe_dataframe(df, ['name', 'zip'], canonicalize=True, sample_size=1)

然后控制台会要求您标记一些示例。 如果重复点击'y',否则点击'n'。完成后单击“f”完成。 然后它将对整个数据帧执行重复数据删除。

【讨论】:

    【解决方案2】:

    对于邮政编码,我可以相当自信地说,如果没有一些字段验证机制,您将无法检测到拼写错误(两个邮政编码可能看起来非常接近并且都是有效的邮政编码)

    如果对数据进行了排序,则对拼写错误的位置有一些假设(第一个字母极不可能,除非在常见替换的情况下),您可能可以利用这一点并将它们作为不同的每个字母块进行搜索。如果您假设姓氏相同,则可以将它们分成 26^2 个不同的子组,并且只让它们在其字段中搜索。

    您也可以尝试仅查看原始名字和姓氏的方法。如果您要搜索 700 万个项目,并且您有 6 万个“Johns”,则只需将它们与“Jhon”比较一次即可找到错误,然后搜索“Jhon”并删除或修复它。但这再次假设您将其分解为框架内的名字和姓氏系列(使用 panda 的 str.extract(),使用 "([\w]+) ([\w]+ )" 或一些如您的正则表达式,根据数据要求)

    【讨论】:

    • 我决定不在原始问题中包含名称解析,因为它与问题没有直接关系,但为了记录,我使用 nameparser 包来处理名称的实际解析,它为任务做了合理的工作。
    【解决方案3】:

    string-grouper 包非常适合这个。它使用带有 N-Grams 的 TF-IDF,并且比 levenshtein 快得多。

    from string_grouper import group_similar_strings
    
    def group_strings(strings: List[str]) -> Dict[str, str]:
        series = group_similar_strings(pd.Series(strings))
    
        name_to_canonical = {}
        for i, s in enumerate(strings):
            deduped = series[i]
            if (s != deduped):
                name_to_canonical[s] = deduped
    
        return name_to_canonical
    

    【讨论】:

      猜你喜欢
      • 2020-01-23
      • 2018-09-28
      • 2010-11-05
      • 1970-01-01
      • 2022-08-10
      • 1970-01-01
      相关资源
      最近更新 更多