在变量中连续使用agrep名称,然后创建一个具有最短匹配名称的新变量

时间:2015-01-21 13:53:24

标签: r fuzzy-comparison agrep stringdist

假设公司名称的字符向量,其中名称以各种形式出现。这是10,000行数据帧的小版本;它显示了所需的第二个向量(" two.names")。

structure(list(firm = structure(1:8, .Label = c("Carlson Caspers", 
"Carlson Caspers Lindquist & Schuman P.A", "Carlson Caspers Vandenburgh  Lindquist & Schuman P.A.", 
"Carlson Caspers Vandenburgh & Lindquist", "Carmody Torrance", 
"Carmody Torrance et al", "Carmody Torrance Sandak", "Carmody Torrance Sandak & Hennessey LLP"
), class = "factor"), two.name = structure(c(1L, 1L, 1L, 1L, 
2L, 2L, 2L, 2L), .Label = c("Carlson Caspers", "Carmody Torrance"
), class = "factor")), .Names = c("firm", "two.name"), row.names = c(NA, 
-8L), class = "data.frame")


                                               firm         two.name
1                                       Carlson Caspers  Carlson Caspers
2               Carlson Caspers Lindquist & Schuman P.A  Carlson Caspers
3 Carlson Caspers Vandenburgh  Lindquist & Schuman P.A.  Carlson Caspers
4               Carlson Caspers Vandenburgh & Lindquist  Carlson Caspers
5                                      Carmody Torrance Carmody Torrance
6                                Carmody Torrance et al Carmody Torrance
7                               Carmody Torrance Sandak Carmody Torrance
8               Carmody Torrance Sandak & Hennessey LLP Carmody Torrance

假设向量已按公司名称的字母顺序排序(我相信最短的版本是第一个)。如何使用agrep()从第一个公司名称开始,将其与第二个公司名称匹配,并假设一个紧密匹配 - 将第一个公司名称添加到新列(short.name)中。然后,将它与第三个元素等匹配。所有Carlson变体都将匹配。

如果没有足够的匹配,就像R遇到第一个Carmody一样,重新开始并匹配下一个元素,依此类推,直到下一个不匹配。

如果连续公司之间没有匹配,则R应该继续进行,直到找到匹配为止。

这个问题的答案是使用模糊匹配对整个向量和组进行多年。 Create a unique ID by fuzzy matching of names (via agrep using R)然而,似乎提供了可以解决我问题的部分代码。此问题使用stringdist()stringdist

修改

下面,对象matches是一个显示匹配项的列表,但我不知道代码告诉R"取第一个并转换以下匹配项(如果有的话),到该名称并将该名称放在新的变量列中。"

as.factor(df$firm)
matches <- lapply(levels(df$firm), agrep, x=levels(df$firm), fixed=TRUE, value=FALSE)

1 个答案:

答案 0 :(得分:0)

我去了一个for循环写出来,首先将第一行定义为short.name然后找到匹配项,更新数据帧并选择下一个要查找的数据帧。这就是我所说的“不要试图用一个单一的方式来解决这个问题” - 你必须先以更冗长的方式使它工作,这样你才能理解正在发生的事情。然后,只有你需要,你可以尝试将它压缩成一个oneliner。

firm.txt <- as.character(df$firm)
short.name <- firm.txt[1]
for (i in 2:length(firm.txt)) {
  # i don't know how to write it any prettier
  match <- agrep(short.name, firm.txt)
  if (length(match) > 0) {
    df$two.name[match] <- short.name
    i <- max(match) + 1
    short.name <- firm.txt[i]
  }
}