我有一个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,我将非常感谢您提供有关如何解决上述问题和/或代码的建议。
非常感谢!
编辑:完全忘记了理想的解决方案将匹配并从我的丑陋表中获取完整行,因为我需要存储在其他列中的名称信息。
答案 0 :(得分:1)
我建议看一下fuzzywuzzy
软件包来进行这种匹配。为了满足您的需求,我认为过滤fuzz.token_sort_ratio
或fuzz.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