Объединение двух фреймов данных с использованием нечеткого / приблизительного соответствия строк в R - PullRequest
13 голосов
/ 09 февраля 2010

ОПИСАНИЕ

У меня есть два набора данных с информацией, которую мне нужно объединить. Единственные общие поля, которые у меня есть, это строки, которые не полностью совпадают, и числовое поле, которое может существенно отличаться

Единственный способ объяснить проблему - показать вам данные. Вот a.csv и b.csv . Я пытаюсь объединить B с A.

Есть три поля в B и четыре в A. Название компании (только для файла A), Название фонда, Класс актива и Активы. До сих пор я фокусировался на попытках сопоставить имена фондов, заменяя слова или части строк для создания точных совпадений, а затем используя:

a <- read.table(file = "http://bertelsen.ca/R/a.csv",header=TRUE, sep=",", na.strings=F, strip.white=T, blank.lines.skip=F, stringsAsFactors=T) 
b <- read.table(file = "http://bertelsen.ca/R/b.csv",header=TRUE, sep=",", na.strings=F, strip.white=T, blank.lines.skip=F, stringsAsFactors=T)
merge(a,b, by="Fund.Name") 

Тем не менее, это приводит меня примерно к 30% совпадению. Остальное я должен сделать вручную.

Активы - это числовое поле, которое также не всегда корректно и может сильно отличаться, если у фонда малые активы. Класс активов - это строковое поле, которое «в общем» одинаково в обоих файлах, однако существуют расхождения.

К усложнению добавляются различные серии средств в файле B. Например:

AGF канадское значение

AGF Canadian Value-D

В этих случаях мне нужно выбрать тот, который не сериализован, или выбрать тот, который называется «A», «-A» или «Advisor» в качестве совпадения.

ВОПРОС

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

ИДЕИ

Один метод, который, я думаю, может работать, - это нормализация строк на основе первой заглавной буквы каждого слова в строке. Но я не смог понять, как это осуществить, используя R.

Другим методом, который я рассмотрел, было создание индекса совпадений на основе комбинации активов, названия фонда, класса активов и компании. Но опять же, я не уверен, как это сделать с R. Или, если на то пошло, если это вообще возможно.

Примеры кода, комментарии, мысли и указания приветствуются!

Ответы [ 4 ]

11 голосов
/ 07 июля 2016

Настоятельно рекомендуется использовать пакет dgrtwo / fuzzyjoin . stringdist_inner_join(a,b, by="Fund.Name")

8 голосов
/ 09 февраля 2010

Одно быстрое предложение: попробуйте выполнить сопоставление для разных полей отдельно перед использованием слияния. Самый простой подход - с функцией pmatch, хотя в R нет недостатка в функциях сопоставления текста (например, agrep). Вот простой пример:

pmatch(c("med", "mod"), c("mean", "median", "mode"))

Для вашего набора данных он соответствует всем именам фондов из a:

> nrow(merge(a,b,x.by="Fund.Name", y.by="Fund.name"))
[1] 58
> length(which(!is.na(pmatch(a$Fund.Name, b$Fund.name))))
[1] 238

Как только вы создадите совпадения, вы можете легко объединить их, используя вместо этого.

2 голосов
/ 10 февраля 2010

Приблизительное сопоставление строк не является хорошей идеей, поскольку неправильное сопоставление сделает недействительным весь анализ.Если имена из каждого источника одинаковы каждый раз, то создание индексов мне тоже кажется лучшим вариантом.Это легко сделать в R:

Предположим, у вас есть данные:

a<-data.frame(name=c('Ace','Bayes'),price=c(10,13))
b<-data.frame(name=c('Ace Co.','Bayes Inc.'),qty=c(9,99))

Создайте индекс имен для каждого источника один раз, возможно, используя pmatch и т. Д. В качестве начальной точки, а затемпроверка вручную.

a.idx<-data.frame(name=c('Ace','Bayes'),idx=c(1,2))
b.idx<-data.frame(name=c('Ace Co.','Bayes Inc.'), idx=c(1,2))

Затем для каждого запуска слияния используйте:

a.rich<-merge(a,a.idx,by="name")
b.rich<-merge(b,b.idx,by="name")
merge(a.rich,b.rich,by="idx")

Что даст нам:

  idx name.x price     name.y qty
1   1    Ace    10    Ace Co.   9
2   2  Bayes    13 Bayes Inc.  99
1 голос
/ 10 февраля 2010

Я тоже местный житель Канады, узнаю названия фондов.

Это сложный вопрос, поскольку каждый из поставщиков данных выбирает свою форму для имен отдельных фондов. Некоторые используют различную структуру, как и все остальные, либо в Фонде, либо в классе, другие повсюду. Кажется, что каждый выбирает свои собственные короткие формы, и они регулярно меняются.

Вот почему так много людей, как вы, делают это вручную. Некоторые из консалтинговых фирм перечисляют индексы для связи с различными источниками, не уверены, что вы изучили этот маршрут?

Как указали Шейн и Марек, это скорее совместимая задача, чем прямое соединение. Многие компании борются с этим. Я нахожусь в середине моей работы над этим ...

Jay

...