繁体   English   中英

删除有拼写错误的 Pandas 数据帧的最有效方法是什么?

[英]What is the most efficient way to dedupe a Pandas dataframe that has typos?

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

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

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

我一直在使用 Levenshtein 距离来计算来自Fuzzywuzzy 包的两个字符串之间的距离,当数据帧很小并且我可以通过以下方式遍历它时,它非常有效:

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

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

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

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”完成。 然后它将对整个数据帧执行重复数据删除。

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

如果对数据进行排序,并假设错别字出现在何处(第一个字母极不可能出现,除非是常见替换的情况),您可能能够利用这一点并将它们作为不同的每个字母块进行搜索。 如果您假设姓氏相同,则可以将它们分成 26^2 个不同的子组,并且只让它们在各自的领域内进行搜索。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM