R:使用agrep和data.table进行模糊合并

时间:2018-09-19 09:38:09

标签: r data.table agrep

我尝试合并两个data.tables,但是由于股票名称的拼写不同,我丢失了大量的数据点。因此,我正在寻找模糊合并,而不是精确匹配。

library("data.table")
dt1 = data.table(Name = c("ASML HOLDING","ABN AMRO GROUP"), A = c(1,2))
dt2 = data.table(Name = c("ASML HOLDING NV", "ABN AMRO GROUP"), B = c("p", "q"))

在“名称”上合并dt1和dt2时,由于添加了“ NV”,将排除ASML HOLDING,而实际数据将是准确的。

首选的最终数据输出看起来像:

              Name A B
1:  ABN AMRO GROUP 2 q
2: ASML HOLDING NV 1 p

我接下来尝试的是以下内容:

dt1 = dt1[, dt2_NAME := agrep(dt1$Name, dt2$Name, ignore.case = TRUE, value = TRUE, max.distance = 0.05, useBytes = TRUE)]

但是,出现以下错误

  

参数“模式”的长度> 1,并且仅使用第一个元素

该错误是合理的,因为dt1 $ Name大于1,但我认为如果逐行考虑dt1 $ Name,这将是一个可行的解决方案。

这可能是一个愚蠢的错误,但是由于某种原因,我无法解决这个问题。此外,我更喜欢使用data.table,因为我的数据集相当大,到目前为止,它的工作非常出色。此外,我是堆栈溢出的新手,如果我的问题有所欠缺,敬请原谅。

最后,我找到了一段可以完成工作的代码,但是对于实际使用而言太慢了。 Fuzzy merge in R

dt1$Name_dt2 <- "" # Creating an empty column
for(i in 1:dim(dt1)[1]) {
  x <- agrep(dt1$Name[i], dt2$Name,
             ignore.case=TRUE, value=TRUE,
             max.distance = 0.05, useBytes = TRUE)
  x <- paste0(x,"")
  dt1$Name_dt2[i] <- x
}

1 个答案:

答案 0 :(得分:1)

使用'fuzzyjoin'的可能解决方案:

library(fuzzyjoin)
f <- Vectorize(function(x,y) agrepl(x, y,
                                   ignore.case=TRUE,
                                   max.distance = 0.05, useBytes = TRUE))

dt1 %>% fuzzy_inner_join(dt2, by="Name", match_fun=f)
#          Name.x A          Name.y B
#1   ASML HOLDING 1 ASML HOLDING NV p
#2 ABN AMRO GROUP 2  ABN AMRO GROUP q

注意:您也遇到的主要问题是agrepagrepl似乎并不期望第一个参数是向量。这就是我用Vectorize包裹通话的原因。

此方法可以与等值联接一起使用(请注意by中的列顺序!):

dt1 = data.frame(Name = c("ASML HOLDING","ABN AMRO GROUP"), A = c(1,2),Date=c(1,2))
dt2 = data.frame(Name = c("ASML HOLDING NV", "ABN AMRO GROUP", "ABN AMRO GROUP"), B = c("p", "q","r"),Date=c(1,2,3))

dt1 %>% fuzzy_inner_join(dt2, by=c("Date","Name"), match_fun=f) %>% filter(Date.x==Date.y)