如何准匹配两个字符串向量(在R中)?

机器算法验证 r 文本挖掘
2022-02-07 13:27:45

我不确定这应该如何命名,所以如果你知道更好的术语,请纠正我。

我有两个清单。55 个项目之一(例如:字符串向量),另一个是 92 个。项目名称相似但不相同。

我希望在 92 列表中找到最佳候选s到 55 列表中的项目(然后我将通过它并选择正确的拟合)。

如何做呢?

我的想法在哪里:

  1. 查看所有匹配的(使用某些列表?匹配)
  2. 尝试字符串向量之间的距离矩阵,但我不确定如何最好地定义它(相同字母的数量,字符串的顺序如何?)

那么什么包/功能/研究领域处理这样的任务,以及如何处理?

更新:这是我希望匹配的向量示例

vec55 <- c("Aeropyrum pernix", "Archaeoglobus fulgidus", "Candidatus_Korarchaeum_cryptofilum", 
"Candidatus_Methanoregula_boonei_6A8", "Cenarchaeum_symbiosum", 
"Desulfurococcus_kamchatkensis", "Ferroplasma acidarmanus", "Haloarcula_marismortui_ATCC_43049", 
"Halobacterium sp.", "Halobacterium_salinarum_R1", "Haloferax volcanii", 
"Haloquadratum_walsbyi", "Hyperthermus_butylicus", "Ignicoccus_hospitalis_KIN4", 
"Metallosphaera_sedula_DSM_5348", "Methanobacterium thermautotrophicus", 
"Methanobrevibacter_smithii_ATCC_35061", "Methanococcoides_burtonii_DSM_6242"
)
vec91 <- c("Acidilobus saccharovorans 345-15", "Aciduliprofundum boonei T469", 
"Aeropyrum pernix K1", "Archaeoglobus fulgidus DSM 4304", "Archaeoglobus profundus DSM 5631", 
"Caldivirga maquilingensis IC-167", "Candidatus Korarchaeum cryptofilum OPF8", 
"Candidatus Methanoregula boonei 6A8", "Cenarchaeum symbiosum A", 
"Desulfurococcus kamchatkensis 1221n", "Ferroglobus placidus DSM 10642", 
"Halalkalicoccus jeotgali B3", "Haloarcula marismortui ATCC 43049", 
"Halobacterium salinarum R1", "Halobacterium sp. NRC-1", "Haloferax volcanii DS2", 
"Halomicrobium mukohataei DSM 12286", "Haloquadratum walsbyi DSM 16790", 
"Halorhabdus utahensis DSM 12940", "Halorubrum lacusprofundi ATCC 49239", 
"Haloterrigena turkmenica DSM 5511", "Hyperthermus butylicus DSM 5456", 
"Ignicoccus hospitalis KIN4/I", "Ignisphaera aggregans DSM 17230", 
"Metallosphaera sedula DSM 5348", "Methanobrevibacter ruminantium M1", 
"Methanobrevibacter smithii ATCC 35061", "Methanocaldococcus fervens AG86", 
"Methanocaldococcus infernus ME", "Methanocaldococcus jannaschii DSM 2661", 
"Methanocaldococcus sp. FS406-22", "Methanocaldococcus vulcanius M7", 
"Methanocella paludicola SANAE", "Methanococcoides burtonii DSM 6242", 
"Methanococcus aeolicus Nankai-3", "Methanococcus maripaludis C5", 
"Methanococcus maripaludis C6", "Methanococcus maripaludis C7", 
"Methanococcus maripaludis S2", "Methanococcus vannielii SB", 
"Methanococcus voltae A3", "Methanocorpusculum labreanum Z", 
"Methanoculleus marisnigri JR1", "Methanohalobium evestigatum Z-7303", 
"Methanohalophilus mahii DSM 5219", "Methanoplanus petrolearius DSM 11571", 
"Methanopyrus kandleri AV19", "Methanosaeta thermophila PT", 
"Methanosarcina acetivorans C2A", "Methanosarcina barkeri str. Fusaro", 
"Methanosarcina mazei Go1", "Methanosphaera stadtmanae DSM 3091", 
"Methanosphaerula palustris E1-9c", "Methanospirillum hungatei JF-1", 
"Methanothermobacter marburgensis str. Marburg", "Methanothermobacter thermautotrophicus str. Delta H", 
"Nanoarchaeum equitans Kin4-M", "Natrialba magadii ATCC 43099", 
"Natronomonas pharaonis DSM 2160", "Nitrosopumilus maritimus SCM1", 
"Picrophilus torridus DSM 9790", "Pyrobaculum aerophilum str. IM2", 
"Pyrobaculum arsenaticum DSM 13514", "Pyrobaculum calidifontis JCM 11548", 
"Pyrobaculum islandicum DSM 4184", "Pyrococcus abyssi GE5", "Pyrococcus furiosus DSM 3638", 
"Pyrococcus horikoshii OT3", "Staphylothermus hellenicus DSM 12710", 
"Staphylothermus marinus F1", "Sulfolobus acidocaldarius DSM 639", 
"Sulfolobus islandicus L.D.8.5", "Sulfolobus islandicus L.S.2.15", 
"Sulfolobus islandicus M.14.25", "Sulfolobus islandicus M.16.27", 
"Sulfolobus islandicus M.16.4", "Sulfolobus islandicus Y.G.57.14", 
"Sulfolobus islandicus Y.N.15.51", "Sulfolobus solfataricus P2", 
"Sulfolobus tokodaii str. 7", "Thermococcus gammatolerans EJ3", 
"Thermococcus kodakarensis KOD1", "Thermococcus onnurineus NA1", 
"Thermococcus sibiricus MM 739", "Thermofilum pendens Hrk 5", 
"Thermoplasma acidophilum DSM 1728", "Thermoplasma volcanium GSS1", 
"Thermoproteus neutrophilus V24Sta", "Thermosphaera aggregans DSM 11486", 
"Vulcanisaeta distributa DSM 14429", "uncultured methanogenic archaeon RC-I"
) 
4个回答

我有过类似的问题。(在这里看到:https ://stackoverflow.com/questions/2231993/merging-two-data-frames-using-fuzzy-approximate-string-matching-in-r )

我收到的大多数建议都围绕着:

pmatch(), 和agrep(),是三个函数,如果您花时间仔细阅读grep()grepl()它们将为您提供一些关于通过近似字符串或近似正则表达式进行近似字符串匹配的见解。

没有看到字符串,很难为您提供如何匹配它们的硬示例。如果您可以向我们提供一些示例数据,我相信我们可以找到解决方案。

我发现另一个效果很好的选项是压平字符串,tolower()查看字符串中每个单词的第一个字母,然后进行比较。有时这很顺利。然后还有更复杂的事情,比如其他答案中提到的距离。有时这些工作,有时它们很可怕 - 这真的取决于弦。

我们能看到他们吗?

更新

看起来 agrep() 可以解决大多数问题。请注意, agrep() 只是 R 对 Levenshtein 距离的实现。

agrep(vec55[1],vec91,value=T)

虽然有些人不计算,但我什至不确定 Ferroplasm acidaramus 是否与 Ferroglobus placidus DSM 10642 相同,例如:

agrep(vec55[7],vec91,value=T) 

我认为您可能对其中一些有点 SOL,也许从头开始创建索引是最好的选择。IE,。用 vec55 的 id 编号创建一个表,然后在 vec91 中手动创建对 vec55 中 id 的引用。我知道这很痛苦,但很多事情都可以用 agrep() 来完成。

有很多方法可以测量两个字符串之间的距离。在 R 中广泛实施的两种重要(标准)方法是 Levenshtein 和 Hamming 距离。前者在“MiscPsycho”包中可用,后者在“e1071”包中。使用这些,我将简单地计算成对距离的 92 x 55 矩阵,然后从那里继续(即列表 1 中字符串“1”的最佳候选匹配是列表 2 中与字符串“1”的距离最小的字符串“x” ”)。

或者,RecordLinkage 包中有一个函数 compare(),它似乎旨在做你想做的事,并使用所谓的 Jaro-Winkler距离,这似乎更适合手头的任务,但我没有经验.

编辑:我正在编辑我的答案以包括 Brandon 的评论以及 Tal 的代码,以找到与vec55的第一个条目“Aeropyrum pernix”的匹配项:

agrep(vec55[1],vec91,ignore.case=T,value=T,max.distance = 0.1, useBytes = FALSE)
[1] "Aeropyrum pernix K1"

为了补充郭的有用答案,请允许我添加一些简单的原则和想法。确定指标的一个好方法是考虑字符串与目标的差异。当变体是排版错误的组合时,“编辑距离”很有用,例如换位邻居或错误键入单个键。

另一种有用的方法(具有略微不同的理念)是将每个字符串映射到一个代表相关字符串的类别。Soundex ”方法做到了这一点:一个单词的Soundex代码是一个由四个字符组成的序列,编码了主辅音和发音相似的内部结果组。当单词是拼音错误或彼此变体时使用。在示例应用程序中,您将获取所有目标词,其 Soundex 代码等于每个探测词的 Soundex 代码。(以这种方式可以获取零个或多个目标。)

除了 Kwak 的其他建议外,我还建议您查看N-gramDamerau-Levenshtein距离。

这篇论文比较了这里提到的几个不同编辑距离的准确率(据google学者高度引用)。

正如您所看到的,有许多不同的方法可以解决这个问题,您甚至可以组合不同的指标(我链接到的论文谈到了这一点)。我认为 Levenshtein 和基于相关的指标具有最直观的意义,特别是如果由于人工打字而发生错误。N-gram 也很简单,并且对于不是名称或单词的数据有意义。

虽然 soundex 是一种选择,但我所看到的一点点工作(诚然是非常少量的)soundex 的性能不如 Levenshstein 或其他匹配名称的编辑距离。Soundex 仅限于可能由人类打字员输入的语音短语,其中 Levenshtein 和 N-gram 可能具有更广泛的范围(尤其是 N-gram,但我希望 Levenshtein 距离对于非单词也能表现更好)。

就包而言,我无能为力,但是 N-gram 的概念非常简单(我最近确实制作了一个 SPSS 宏来执行 N-gram,但是对于这样一个小项目,我只会使用已经制作的包R其他海报建议)。是在 python 中计算 Levenshtein 距离的示例。