Я пытаюсь использовать stringdist для нечеткого сопоставления названий компаний между двумя фреймами данных, но это работает не очень хорошо, что можно сделать?

У меня есть фрейм данных с 5 миллионами различных названий компаний, многие из которых относятся к одной и той же компании, написанной по-разному или с орфографическими ошибками. В качестве примера я использую название компании «Amminex», а затем пытаюсь разбить его на 5 миллионов названий компаний:

Companylist <- data.frame(Companies=c('AMMINEX'))

Это мой большой список названий компаний, которые я открываю:

Biglist <- data.frame(name=c(Biglist[,]))

Я помещаю AMMINEX и 5 миллионов компаний в одну матрицу:

Matches <- expand.grid(Companylist$Companies,Biglist$name.Companiesnames)

Измените имена столбцов:

names(Matches) <- c("Companies","CompaniesList")

Я использую stringdist с методом косинуса:

Matches$dist <- stringdist(Matches$Companies,Matches$CompaniesList, method="cosine")

Я удаляю все расстояния выше 0,2, чтобы избавиться от плохих совпадений:

Matches_trimmed <- Matches[!(Matches$dist>0.2),]

Я сортирую по столбцу расстояния, чтобы лучшие совпадения отображались вверху:

Matches_trimmed <- Matches_trimmed[with(Matches_trimmed, order(dist)), ]

Как видите, результаты не очень удовлетворительны: введите здесь описание изображения

Первая строка хороша, но затем появляется куча плохих совпадений, прежде чем, наконец, внизу я получаю хорошие совпадения «AMMINEX AS».

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


person WoeIs    schedule 31.03.2018    source источник
comment
с именами лучше использовать метрику Яро или Яро-Винклера   -  person phiver    schedule 31.03.2018
comment
@phiver Спасибо за предложение. Я попробовал jw в методах, и он действительно работал лучше. i.imgur.com/WoU4RvK.png Тем не менее, он по-прежнему соответствует таким названиям, как LAMINEX и ARMINE с относительно низкими значениями расстояния. Я боюсь, что как только я добавлю больше компаний для сопоставления, мне будет трудно определить значение предельного расстояния, чтобы гарантировать сохранение полезных совпадений и отбрасывание как можно большего количества плохих совпадений.   -  person WoeIs    schedule 31.03.2018
comment
Есть ли у вас другая информация о компаниях, которую вы могли бы использовать для определения вероятности совпадения? Возможно, стоит изучить пакет RecordLinkage, который позволит вам попытаться сопоставить множество ковариатов и упростит поиск порога для совпадения с алгоритмом EM.   -  person gfgm    schedule 31.03.2018
comment
@gfgm Я просмотрел пакет RecordLinkage. К сожалению, на данный момент я не могу найти никакой информации, кроме их имен. Есть ли что-нибудь в пакете RecordLinkage, что может соответствовать порядку букв в именах? Я предполагаю, что метрика Яро-Винклера уже делает это?   -  person WoeIs    schedule 31.03.2018
comment
@WoeIs, вы можете использовать jw с p = 0,1. Это дает штраф за сопоставление. Но решение о том, что лучше всего будет отсечь, будет зависеть от вас. Я предлагаю пройтись по нескольким компаниям и посмотреть, является ли значение ниже 0,1 хорошей целью.   -  person phiver    schedule 31.03.2018
comment
Вы всегда можете добавить столбцы, которые, по вашему мнению, представляют собой свидетельство совпадения, например. если вы считаете, что многие ошибки имеют форму "true_name garbage", вы можете создать дополнительную коварианту, которая представляет собой первые n букв названия компании, и попытаться найти точные совпадения в названии основы в дополнение к нечетким совпадениям в целом -- это добавило бы веса таким шаблонам, как "AMMINEX" -> "AMMINEX AS"   -  person gfgm    schedule 31.03.2018
comment
@phiver Возможно, мне придется пойти по этому пути, спасибо!   -  person WoeIs    schedule 31.03.2018
comment
@gfgm Звучит как интересная процедура! Какую команду из пакета вы бы посоветовали использовать для этого? Я просмотрел список команд в пакете, но мне немного сложно сказать, какая из них добавляет ковариант.   -  person WoeIs    schedule 31.03.2018
comment
@WoeIs его нет в пакете, вам нужно будет сделать это заранее вручную для двух кадров данных, которые вы хотите сопоставить, например. df1$stem_n <- substr(df1$name, 1, n) и т. д.   -  person gfgm    schedule 31.03.2018
comment
@gfgm Спасибо за предложение. К сожалению, я не совсем уверен, как включить substr в мой предыдущий код. Я все еще на очень начальном уровне, поэтому все, что я смог сделать, это сократить имя AMMINEX на основе свойств, которые я указал в substr. Что мне кажется главной проблемой, так это то, что такие компании, как LAMINEX, все еще появляются, и я не могу найти никакого алгоритма, который мог бы увидеть разницу между AMMINEX и LAMINEX.   -  person WoeIs    schedule 31.03.2018
comment
Попробуйте метрики qgrams и Jaccard в stringdist. Оба они используют n-граммы, поэтому порядок букв имеет значение. Вы можете «настроить» значение n, чтобы найти лучшее решение для вашей задачи, но я обнаружил, что 2 работает хорошо.   -  person Relasta    schedule 31.03.2018
comment
@Relasta К сожалению, эти показатели тоже не очень помогли.   -  person WoeIs    schedule 31.03.2018