【问题标题】:Match rows containing a word with permutations匹配包含带有排列的单词的行
【发布时间】:2010-10-18 10:34:32
【问题描述】:

假设您有一个包含 varchar 列的大表。

您将如何匹配在 varchar col 中包含“首选”一词但数据有些嘈杂且偶尔包含拼写错误的行,例如:

['$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',]

【问题讨论】:

  • 您是专门询问“首选”,还是这是一个普遍问题?
  • 还有少量其他类似的例子

标签: nlp information-retrieval


【解决方案1】:

您能否尝试在表格的一小部分样本上对其进行训练以查找可能的拼写错误(使用 split + Levenshtein),然后在整个表格中使用生成的单词列表?

【讨论】:

    【解决方案2】:

    再创建两个表,分别是拼写和可能的拼写:

    --你可以找出类型

    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】:

      正在尝试用 TSQL 或什么语言执行此操作?

      您也许可以使用正则表达式来匹配其中的大多数。

      以下的一些变化

      "p(er|re|e)f{1,2}er{1,2}ed"
      
      "r(e|i)s?t(ri|ir|rti|i)ct?ed"
      

      你想确保它不是大写敏感...

      【讨论】:

      • 它是 mysql,它的正则表达式支持还有很多不足之处,但应该能够处理这样的事情
      • 对“受限”有什么想法吗?这可能就是我所需要的
      • "r(e|i)s?t(ri|ir|rti|i)ct?ed" 你想确保它不是大写敏感...
      • 这适用于您提供的所有示例...您可能需要稍微调整一下,如果您需要帮助,请告诉我。
      【解决方案4】:

      我可能会做这样的事情——如果你能摆脱 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 示例。

      【讨论】:

        猜你喜欢
        • 2020-02-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-01
        • 1970-01-01
        • 2011-09-09
        • 1970-01-01
        • 2010-12-25
        相关资源
        最近更新 更多