细微差别的模糊匹配

Fuzzy matching for slight difference

我有一列公司名称,我想计算该列中有多少家不同的公司。在这个栏目中,一些相同的公司名称略有不同,例如,这些公司应该只计算一次。

ASAHI INTECC CO., LTD.
Asahi Intecc USA Inc
ASAHI INTECC USA, INC

我想要通用的代码,可以精确统计公司的数量,而不是重复计算有细微差异的公司。 例如,此可重现数据应 return 值为 6

company <- read.table(text = "
          CompanyName
          'MERCK SHARP & DOHME CORPORATION'
          'GILEAD SCIENCES INC'
          'BOEHRINGER INGELHEIM PHARMACEUTICALS, INC.'
          'ABBVIE, INC.'
          'JANSSEN SCIENTIFIC AFFAIRS, LLC'
          'BOEHRINGER INGELHEIM PHARMA GMBH & CO.KG'
          'ASAHI INTECC CO., LTD.'
          'Asahi Intecc USA Inc'
", header = TRUE, stringsAsFactors = FALSE)

我看了 How can I match fuzzy match strings from two datasets? 但我仍然不知道如何构建代码。希望大家多多指教

要比较字符串之间的相似性,第一步通常是使用您所掌握的最佳知识清理数据:

由于很多计算字符串距离的方法会将大小写字母视为不同的字母,所以首先要将所有字符转换为相同的大小写。您可以进行任何其他清洁以帮助提高准确性。

library(dplyr)
companyName <- company$CompanyName %>%
    toupper() %>% # convert to upper case
    stringr::str_replace_all("\s+"," ") %>% # convert any consecutive whitespaces to single space
    stringr::str_remove_all("\.|,") # remove all comma or dot
> companyName
[1] "MERCK SHARP & DOHME CORPORATION"          "GILEAD SCIENCES INC"                      "BOEHRINGER INGELHEIM PHARMACEUTICALS INC"
[4] "ABBVIE INC"                               "JANSSEN SCIENTIFIC AFFAIRS LLC"           "BOEHRINGER INGELHEIM PHARMA GMBH & COKG" 
[7] "ASAHI INTECC CO LTD"                      "ASAHI INTECC USA INC"    

计算字符串距离:

distanceMatrix <- stringdist::stringdistmatrix(
    a = companyName,
    b = companyName,
    # You can pick the method that works best for your data. Also, manual inspection is needed. See ?stringdist 
    # I'm picking soundex for this example
    method = "soundex"
)

使用soundex方法,如果一个单元格是0,则表示对应的行和列非常接近

> distanceMatrix
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]    0    1    1    1    1    1    1    1
[2,]    1    0    1    1    1    1    1    1
[3,]    1    1    0    1    1    0    1    1
[4,]    1    1    1    0    1    1    1    1
[5,]    1    1    1    1    0    1    1    1
[6,]    1    1    0    1    1    0    1    1
[7,]    1    1    1    1    1    1    0    0
[8,]    1    1    1    1    1    1    0    0

这意味着,在companyName向量中,第3项接近第6项,第7项接近第8项。

result <- which(distanceMatrix==0,arr.ind = TRUE) %>%
    as.data.frame() %>%
    dplyr::filter(col > row)
> result
  row col
1   3   6
2   7   8

> result %>% mutate_all(~companyName[.x])
                                       row                                     col
1 BOEHRINGER INGELHEIM PHARMACEUTICALS INC BOEHRINGER INGELHEIM PHARMA GMBH & COKG
2                      ASAHI INTECC CO LTD                    ASAHI INTECC USA INC

请注意,在计算字符串距离时,您可以通过清理字符串或选择不同的方法、参数或阈值来提高准确性。但它永远无法保证 100% 的准确性。

最后,要统计独特的公司,我们可以这样做:

> length(companyName) - length(unique(result$row))
[1] 6