假设您有一个包含varchar列的大表。
如何匹配varchar col中包含“preferred”一词的行但是数据有点嘈杂并且偶尔会出现拼写错误,例如:
['$2.10 Cumulative Convertible Preffered Stock, $25 par value',
'5.95% Preferres Stock',
'Class A Preffered',
'Series A Peferred Shares',
'Series A Perferred Shares',
'Series A Prefered Stock',
'Series A Preffered Stock',
'Perfered',
'Preffered C']
上述拼写错误中“首选”一词的排列似乎表现出family resemblance,但它们的共同点很少。请注意,拆分每个单词并在每行中的每个单词上运行levenshtein将会非常昂贵。
更新:
还有其他一些例子,例如:与'限制':
['Resticted Stock Plan',
'resticted securities',
'Ristricted Common Stock',
'Common stock (restrticted, subject to vesting)',
'Common Stock (Retricted)',
'Restircted Stock Award',
'Restriced Common Stock',]
答案 0 :(得分:1)
您是否可以尝试在桌子的一小部分样本上进行训练,以找到可能的拼写错误(使用split + Levenshtein),然后在整个表格中使用生成的单词列表?
答案 1 :(得分:1)
尝试用TSQL或用什么语言来做?
你可以使用正则表达式击中大部分。
以下
的一些变体"p(er|re|e)f{1,2}er{1,2}ed"
"r(e|i)s?t(ri|ir|rti|i)ct?ed"
你想确保它不是上限敏感的......
答案 2 :(得分:1)
再创建两个表格,拼写和可能的拼写:
- 你可以找出类型
create table spelling ( id, word ) ;
create table possible_spelling
( id, spelling_id references spelling(id), spelling )
-- possible spelling also includes the correct spelling
-- all values are lowercase
insert into spelling( word ) values ('preferred');
insert into possible_spelling( spelling_id, spelling )
select 1, '%preferred%' union select 1, '%prefered%' union ....;
select *
from bigtable a
join possible_spelling b
on (lower(a.data) like b.spelling )
join spelling c on (b.spelling_id = c.id)
where c.word = 'preferred';
异议:这会很慢,需要设置。 答:不是那么慢,这应该是分类和修复数据的一次性事情。一次设置,每个传入行一次进行分类。
答案 3 :(得分:1)
我可能会做这样的事情 - 如果你能一次离开Levenshtein - 这里是an amazing spellchecker implementation by Peter Norvig:
import re, collections
def words(text): return re.findall('[a-z]+', text.lower())
def train(features):
model = collections.defaultdict(lambda: 1)
for f in features:
model[f] += 1
return model
NWORDS = train(words(file('big.txt').read()))
alphabet = 'abcdefghijklmnopqrstuvwxyz'
def edits1(word):
s = [(word[:i], word[i:]) for i in range(len(word) + 1)]
deletes = [a + b[1:] for a, b in s if b]
transposes = [a + b[1] + b[0] + b[2:] for a, b in s if len(b)>1]
replaces = [a + c + b[1:] for a, b in s for c in alphabet if b]
inserts = [a + c + b for a, b in s for c in alphabet]
return set(deletes + transposes + replaces + inserts)
def known_edits2(word):
return set(e2 for e1 in edits1(word) for e2 in edits1(e1) if e2 in NWORDS)
def known(words): return set(w for w in words if w in NWORDS)
def correct(word):
candidates = known([word]) or known(edits1(word)) or known_edits2(word) or [word]
return max(candidates, key=NWORDS.get)
他提供了一套训练集here: http://norvig.com/big.txt以下是示例输出:
>>> correct('prefferred')
'preferred'
>>> correct('ristricted')
'restricted'
>>> correct('ristrickted')
'restricted'
在您的情况下,您可以将原始列复制到新列,但在执行时将其传递给拼写检查程序。然后在拼写正确的列上添加fulltext
索引,并将查询与其匹配,但返回原始列的结果。您只需要执行一次,而不是每次都计算距离。您也可以拼写检查输入,或仅将更正后的版本检查为后备。无论哪种方式,值得研究Norvig的例子。