【问题标题】:Match similar column elements using pandas and fuzzwuzzy使用 pandas 和 fuzzwuzzy 匹配相似的列元素
【发布时间】:2019-03-09 01:23:45
【问题描述】:

我有一个 Excel 文件,其中一列包含 1000 多个公司名称,另一列包含大约 20,000 个公司名称。

目标是匹配尽可能多的名称。问题是第一列 (1000+) 中的名称格式不正确,这意味着“公司名称”字符串可能类似于 "9Com(panynAm9e00"。我'我试图找出解决这个问题的最佳方法。(只有 12 个名称完全匹配)

在尝试了不同的方法后,我最终尝试使用正则表达式匹配每个名称中的 4-5 个或更多字符,具体取决于每个字符串的长度。但我只是在努力寻找最有效的方法来做到这一点。

例如:

第 1 列

 1. 9Com(panynAm9e00 
 2. NikE4 
 3. Mitrosof2

第 2 列

 1. Microsoft
 2. Company Name
 3. Nike

Column 1 中获取第一个元素并在 Column 2 中查找匹配项。如果没有完全匹配,则查找具有 4-5 个相同字符的字符串。

有什么建议吗?

【问题讨论】:

    标签: python pandas fuzzywuzzy


    【解决方案1】:

    我想数字在实际的公司名称中并不是很常见,因此初始过滤步骤将极大地帮助前进,但这里有一个实现,即使没有这个也应该工作得相对好。如果你愿意的话,可以使用 bag-of-letters (bag-of-words) 方法:

    1. 将所有内容(第 1 列和第 2 列)转换为小写
    2. 对于第 2 列中的每个已知公司,存储每个唯一字母,以及它在字典中出现(计数)的次数
    3. 对第 1 列中的每个条目执行相同操作(步骤 2)
    4. 对于第 1 列中的每个条目,从真实公司名称列表中找到最接近的字母袋(第 2 步中的字典)

    字典距离的实现取决于你。

    【讨论】:

      【解决方案2】:

      我建议使用pandaspd.read_excel() 读取您的Excel 文件,然后使用fuzzywuzzy 执行匹配,例如:

      import pandas as pd
      from fuzzywuzzy import process, fuzz
      
      df = pd.DataFrame([['9Com(panynAm9e00'],
              ['NikE4'],
              ['Mitrosof2']],
              columns=['Name'])
      
      known_list = ['Microsoft','Company Name','Nike']
      
      def find_match(x):
      
        match = process.extractOne(x, known_list, scorer=fuzz.partial_token_sort_ratio)[0]
        return match
      
      df['match found'] = [find_match(row) for row in df['Name']]
      

      产量:

                     Name   match found
      0  9Com(panynAm9e00  Company Name
      1             NikE4          Nike
      2         Mitrosof2     Microsoft
      

      【讨论】:

      • 这基本上是我以前用过的方法;取决于您对所涉及名称的了解程度,您可以比普通的“编辑距离”做得更好,例如,生物信息学世界有像 Needleman–Wunsch 算法这样的东西,它可以让您说某些变化或多或少重要
      • @rahlf23 太好了,非常感谢!从未使用过fuzzywyzzy lib,所以很高兴知道。我看了一眼文档,我的猜测是我也可以测量距离作为分数来评估字符串匹配的紧密程度,对吗?因为当我尝试运行测试并使用一对仅共享一个公共字符的非常长的字符串时,它们仍然会显示为匹配项。猜测看距离(或得分 0-100)可以帮助消除不良匹配?再次感谢它。
      • 正确,您可以更改您的scorer,请参见此处:github.com/seatgeek/fuzzywuzzy/issues/137 如果您将extractOne 更改为extract 并返回元组而不是返回,您实际上可以看到每场比赛的得分只是第一个索引[0] 就像我在回答中所做的那样
      • @rahlf23 想再次在这里寻求您的帮助,因为模糊的文档有点不清楚。有没有办法对一对中应匹配多少个字符以使得分为 100 设置某种限制。问题是,例如,某些 3 个字符串将与不正确的名称匹配,以防这 3 个字符在那些更长的字符串中的顺序(例如“Sam”将与“Samsung”匹配)。提前非常感谢。
      • 这是个好问题。在这种情况下,使用partial_token_set_ratio 作为您的scorer 可能会有更好的运气。这是另一个有用的 SO 答案:stackoverflow.com/a/31823872/8146556 在执行匹配之前,您还可以考虑限制您的选项(我上面的答案中的known_list)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-16
      • 2019-02-24
      • 1970-01-01
      相关资源
      最近更新 更多