将名称列表与数据质量差的列匹配(Python)

时间:2018-08-03 14:01:20

标签: python n-gram

我有一个5列的表格,其中之一是数据质量很差的名称列表。我设法在R中尽可能地清理了它,但它仍然看起来像这样(格式化为便于阅读的代码):

Neville Longbottomx
Severus Snape Slyth
Granger, Hermioone
Miss Lovegoo
Nott: Theodore
Mr Potter Gryffindor
Malfoy, Draco
Bulstrode, Millicent
McGonagall, Minerv
Seamus Finnigan Mister
Miss Abbott, Hannah
Ernie Macmillan M
Dumbledore, Albus
Parkinson, Pans" Slyth

现在,我还有另一个名称如下的列表:

Lovegood, Luna
Longbottom, Neville
Macmillan, Ernie
Nott, Theodore
Parkinson, Pansy

我想在第一个列表的第二个列表中找到名称。我查看了有关此内容的其他文章并尝试了this method,因为ngrams似乎是一种明智的选择,但我首先遇到了此错误:

def ngrams(string, n=3):
    string = re.sub(r'[,-./]|\sBD',r'', string)
    ngrams = zip(*[string[i:] for i in range(n)])
    return [''.join(ngram) for ngram in ngrams]


company_names = names['NAMECOLUMN']
vectorizer = TfidfVectorizer(min_df=1, analyzer=ngrams)
tf_idf_matrix = vectorizer.fit_transform(company_names)

Traceback (most recent call last):

  File "<ipython-input-4-687c2896bcf2>", line 17, in <module>
    tf_idf_matrix = vectorizer.fit_transform(company_names)

  File "C:\Program Files\Anaconda3\lib\site-packages\sklearn\feature_extraction\text.py", line 1305, in fit_transform
    X = super(TfidfVectorizer, self).fit_transform(raw_documents)

  File "C:\Program Files\Anaconda3\lib\site-packages\sklearn\feature_extraction\text.py", line 817, in fit_transform
    self.fixed_vocabulary_)

  File "C:\Program Files\Anaconda3\lib\site-packages\sklearn\feature_extraction\text.py", line 752, in _count_vocab
    for feature in analyze(doc):

  File "<ipython-input-4-687c2896bcf2>", line 10, in ngrams
    string = re.sub(r'[,-./]|\sBD',r'', string)

  File "C:\Program Files\Anaconda3\lib\re.py", line 182, in sub
    return _compile(pattern, flags).sub(repl, string, count)

TypeError: expected string or bytes-like object

然后将其作为字符串尝试:

ValueError: empty vocabulary; perhaps the documents only contain stop words

我什至不确定我是否会朝着正确的方向前进,但这是我能找到的最佳链接,它与我需要做的事情相对应,而且我不确定我需要做的更好。我对Python完全陌生,这无济于事:(因此,我希望您对我有所耐心。

A,我将非常感谢您提供有关如何解决上述问题和/或代码的建议。

非常感谢!

编辑:完全忘记了理想的解决方案将匹配并从我的丑陋表中获取完整行,因为我需要存储在其他列中的名称信息。

2 个答案:

答案 0 :(得分:1)

我建议看一下fuzzywuzzy软件包来进行这种匹配。为了满足您的需求,我认为过滤fuzz.token_sort_ratiofuzz.token_set_ratio得分大于某个阈值(例如75%)的名称就足够了

>>> from fuzzywuzzy import fuzz
>>> from itertools import takewhile
>>> 
>>> lstA = ['Neville Longbottomx', 'Severus Snape Slyth', 'Granger, Hermioone', 'Miss Lovegoo', 'Nott: Theodore', 'Mr Potter Gryffindor', 'Malfoy, Draco', 'Bulstrode, Millicent', 'McGonagall, Minerv', 'Seamus Finnigan Mister', 'Miss Abbott, Hannah', 'Ernie Macmillan M', 'Dumbledore, Albus', 'Parkinson, Pans" Slyth']
>>> lstB = ['Lovegood, Luna', 'Longbottom, Neville', 'Macmillan, Ernie', 'Nott, Theodore', 'Parkinson, Pansy']
>>> 
>>> dict((name,next(takewhile(lambda n: fuzz.token_sort_ratio(n, name)>75, lstA), '')) for name in lstB)
{'Lovegood, Luna': '', 'Longbottom, Neville': 'Neville Longbottomx', 'Macmillan, Ernie': '', 'Nott, Theodore': '', 'Parkinson, Pansy': ''}

答案 1 :(得分:1)

您可以使用模糊匹配算法:)

from fuzzywuzzy import fuzz

a = ['Neville Longbottomx','Severus Snape Slyth','Granger, Hermioone','Miss Lovegoo',
    'Nott: Theodore','Mr Potter Gryffindor','Malfoy, Draco','Bulstrode, Millicent',
    'McGonagall, Minerv','Seamus Finnigan Mister','Miss Abbott, Hannah','Ernie Macmillan M',
    'Dumbledore, Albus','Parkinson, Pans" Slyth']

b = ['Lovegood, Luna','Longbottom, Neville','Macmillan, Ernie','Nott, Theodore','Parkinson, Pansy']
get_match_a = []
for name1 in b:
    for name2 in a:
        if fuzz.partial_ratio(name2,name1)>50: # Tune this to fit your need
            get_match_a.append(name2)
            #print(name1,':',name2,'||',fuzz.partial_ratio(name2,name1))
            #uncomment above to see the matching

正如您在下面看到的那样,它非常好用。我希望这会引导您到您要去的地方:)enter image description here