R: Нечеткое слияние с использованием agrep и data.table - PullRequest
0 голосов
/ 19 сентября 2018

Я пытаюсь объединить две таблицы data.table, но из-за разного написания имен акций я теряю значительное количество точек данных.Следовательно, вместо точного совпадения я искал нечеткое слияние.

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 в «Name» ASML HOLDING будет исключен из-за добавления «NV», в то время какфактические данные будут точными.

Предпочтительный вывод окончательных данных будет выглядеть примерно так:

              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)]

Однако я получаю следующую ошибку:

аргумент 'pattern' имеет длину> 1, и будет использоваться только первый элемент

Ошибка имеет смысл, так как dt1 $ Name длиннее 1, но я считаю,это было бы возможным решением, если бы он рассматривал dt1 $ Name от строки к строке.

Это может быть глупой ошибкой, но по какой-то причине я просто не могу разобраться с этим.Кроме того, я предпочитаю использовать data.table, так как мой набор данных довольно большой, и до сих пор он работал великолепно.Кроме того, я новичок в переполнении стека, поэтому извините, если мой вопрос несколько не в порядке.

Наконец, я нашел фрагмент кода, который выполняет свою работу, но слишком медленный для практического использования. Нечеткое слияние в 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 голосов
/ 19 сентября 2018

Возможное решение с использованием '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

ПРИМЕЧАНИЕ. Основная проблема, с которой вы тоже столкнулись, заключалась в том, что agrep и agrepl не ожидали, что первый аргументбыть векторомВот почему я обернул вызов 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)
...