Подтвердить что ты не робот

Как измерить сходство между строками?

У меня есть куча имен, и я хочу получить уникальные имена. Однако из-за орфографических ошибок и несоответствий в данных имена могут быть записаны неправильно. Я ищу способ проверить вектор строк, если два из них подобны.

Например:

pres <- c(" Obama, B.","Bush, G.W.","Obama, B.H.","Clinton, W.J.")

Я хочу найти, что " Obama, B." и "Obama, B.H." очень похожи. Есть ли способ сделать это?

4b9b3361

Ответ 1

Это можно сделать на основании, например, расстояния Левенштейна. В разных пакетах реализовано несколько реализаций. Некоторые решения и пакеты можно найти в ответах на эти вопросы:

Но чаще всего agrep будет делать то, что вы хотите:

> sapply(pres,agrep,pres)
$` Obama, B.`
[1] 1 3

$`Bush, G.W.`
[1] 2

$`Obama, B.H.`
[1] 1 3

$`Clinton, W.J.`
[1] 4

Ответ 2

Может быть, agrep - это то, что вы хотите? Он ищет приблизительные совпадения, используя расстояние редактирования Левенштейна.

lapply(pres, agrep, pres, value = TRUE)

[[1]]
[1] " Obama, B."  "Obama, B.H."

[[2]]
[1] "Bush, G.W."

[[3]]
[1] " Obama, B."  "Obama, B.H."

[[4]]
[1] "Clinton, W.J."

Ответ 3

Добавьте еще один дубликат, чтобы показать, что он работает с несколькими дубликатами.

pres <- c(" Obama, B.","Bush, G.W.","Obama, B.H.","Clinton, W.J.", "Bush, G.")

adist показывает длину строки между 2 символьными векторами

adist(" Obama, B.", pres)
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    0    9    3   10    7

Например, чтобы выбрать ближайшую строку для " Obama, B." вы можете взять ту, которая имеет минимальное расстояние. Чтобы избежать идентичной строки, я принимал только расстояния больше нуля:

d <- adist(" Obama, B.", pres)
pres[min(d[d>0])]
# [1] "Obama, B.H."

Чтобы получить уникальные имена, с учетом орфографических ошибок и несоответствий, вы можете сравнить каждую строку со всеми предыдущими. Тогда, если есть аналогичный, удалите его. Я создал функцию keepunique() которая выполняет это. keepunique() затем применяется ко всем элементам вектора последовательно с помощью Reduce().

keepunique <-  function(x, previousones){
    if(any(adist(x, previousones)<5)){
        x <- NULL
    }
    return(c(previousones, x))
}
Reduce(keepunique, pres)
# [1] "Bush, G."      "Clinton, W.J." "Obama, B.H."