Метрики расстояния между строками в пользу подстроки и независимого порядка слов?

Для моей проблемы с аналитикой данных мне обычно нужно регулировать имена, которые называют A и B, я бы считал их одинаковыми или очень похожими, если A и B имеют значительное количество общих подстрок, независимо от порядка этих подстрок.

Например, для "ХОЛОД" и c("НАПОЛНЕНИЕ", "ХОЛОД/ХОЛОД ВЕТЕРОМ") я бы хотел выбрать "ХОЛОД/ХОЛОД ВЕТЕРОМ", чтобы оно было больше похоже на "ХОЛОД", чем на "НАВОДНЕНИЕ".

Мое текущее задание находится в R. Итак, мои конкретные вопросы заключаются в следующем:

  1. Существуют ли такие метрики, уже определенные в R?

  2. Можно ли предоставить свою собственную реализацию и как-то интегрировать ее с пакетом R stringdist?

Для моего требования я мог бы просто использовать поиск по регулярному выражению, если бы я мог найти A в B или B в A, я могу просто считать их расстояние равным 0.

Большое спасибо!

Редактировать:

В контексте следующего:

> vv <- c("FLOOD", "COLD/WIND CHILL")
> sapply(vv, adist, y = "COLD")
          FLOOD COLD/WIND CHILL 
              3              11 

Я бы хотел, чтобы расстояние от "ХОЛОД" до "ХОЛОД/ВЕТЕР ХОЛОД" было бы меньше, чем от "ХОЛОД" до "НАПОЛНЕНИЕ".

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

Редактировать1:

Моя первоначальная проблема была решена. Вот продолжение со связанной проблемой использования amatch из stringdist в R:

Мне кажется, что я не смог воспроизвести эквивалентный результат тех, что с adist, и даже stringdist в одном пакете с amatch.

Ниже приведена иллюстрация:

vv <- c("FLOOD", "COLD/WIND CHILL")
sapply(vv, adist, y = "COLD",costs=list(deletions=0))
          FLOOD COLD/WIND CHILL 
              2               0 

    stringdist("COLD", c("FLOOD", " COLD/WIND CHILL"), method = 'lv', weight=c(0.001, 0.99, 0.99, 0.99))
[1] 1.981 1.002

amatch("COLD", c("FLOOD", " COLD/WIND CHILL"), method = 'lv', weight=c(0.0001, 0.999, 0.999, 0.999), maxDist = 100)
[1] 1

В приведенном выше контексте, используя вычисление stringdist, amatch должно возвращать 2 вместо 1.

На основании документа stringdist,

"вес:
Для метода = 'osa' или 'dl' штраф за удаление, вставку, замену и транспонирование в указанном порядке. Если метод = 'lv', штраф за транспонирование игнорируется."

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

Я бы предположил, что amatch будет использовать stringdist для выполнения вычислений, но кажется странным, что поведение amatch противоречит поведению stringdist!

Я хочу, чтобы amatch работало, чтобы мне не приходилось повторно реализовывать его, используя adist или stringdist.

Спасибо за помощь еще раз.


person Yu Shen    schedule 14.03.2015    source источник


Ответы (2)


Вы можете использовать adist для нечеткого расстояния. Расстояние представляет собой обобщенное расстояние Левенштейна.

vv <- c("COLD","FLOOD")
sapply(vv,adist,y="COLD/WIND CHILL")
## COLD FLOOD   
##  11    13    ## the distance to COLD < distance to FLOOD

редактировать после обновления OP:

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

sapply(vv, adist, y = "COLD",costs=list(deletions=0))
  FLOOD COLD/WIND       CHILL 
          2               0 
person agstudy    schedule 14.03.2015
comment
Извините, я пробовал в своем контексте, это все равно не решает мою проблему. Пожалуйста, смотрите мои правки выше. - person Yu Shen; 14.03.2015

Вот одно из направлений. По сути, он намеревается разбить ваш текст на триграммы (последовательности из трех букв) и вернуть ассоциации между каждой триграммой и всеми остальными, если они достигают установленного вами уровня (здесь 0,8). Глюк в том, что этот код работает только на уровне слов, а не на уровне триграмм, как положено. Возможно, если бы текстовый файл был больше, была бы разница?

library(tm)
library("RWeka")
text <- c("FLOOD", "COLD/WIND CHILL", "OLD", "FRIGID", "FLOW") 

BigramTokenizer <- function(x) NGramTokenizer(x, Weka_control(min = 3, max = 3))

corpus <- Corpus(VectorSource(text))

tdm <- TermDocumentMatrix(corpus, control = list(tokenize = BigramTokenizer))

lapply(tdm$dimnames$Terms, function(x) findAssocs(tdm, x, 0.8))
person lawyeR    schedule 14.03.2015