Вычисление процента сходства в текстовых строках путем исключения идентичных записей в R

данный скрипт R вычисляет сходство в % между двумя именами, как показано на рисунке. Здесь у нас есть два столбца «names1» и «names2» с соответствующими идентификаторами в id1 и id2. Мое требование состоит в том, что когда мы выполняем скрипт, каждое имя в «names1» сравнивается с каждым именем в столбце «names2», я не хочу, чтобы одна и та же запись, т.е. столбец (id1,names1), сравнивалась с его идентичной записью в ( столбец id2,names2). Например, первая (id1,names1) запись (1,Prabhudev Ramanujam) должна сравниваться со всеми (id2,names2), но не с первой (id2,names2) записью. Аналогично для всех пар. Также, если формула

percent(sapply(names1, function(i)RecordLinkage::levenshteinSim(i,names2))) 

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

library(stringdist)
library(RecordLinkage)
library(dplyr)
library(scales)
id1    <- 1:8 
names1 <- c("Prabhudev Ramanujam","Deepak Subramaniam","Sangamer 
Mahapatra","SriramKishore Sharma",
        "Deepak Subramaniam","SriramKishore Sharma","Deepak 
Subramaniam","Sangamer Mahapatra")
id2    <- c(1,2,3,4,11,13,9,10)
names2 <- c("Prabhudev Ramanujam","Deepak Subramaniam","Sangamer 
Mahapatra","SriramKishore Sharma",
        "Deepak Subramaniam","Sangamer Mahapatra","SriramKishore 
Sharma","Deepak Subramaniam")
Name_Data <- data.frame(id1,names1,id2,names2)
Percent<- percent(sapply(names1, function(i) 
RecordLinkage::levenshteinSim(i,names2)))
Total_Value <- data.frame(id2,names2,Percent)

Визуальный снимок


person Adam Shaw    schedule 06.01.2018    source источник
comment
Когда вы сравниваете один элемент со всеми другими значениями, выходной вектор будет равен 56.   -  person akrun    schedule 06.01.2018
comment
@akrun, спасибо за ответ здесь, я думаю, 60, так как когда вы запускаете переменную Name_Data, вы видите, что четыре значения идентичны, поэтому их следует исключить, результирующий вектор показывает 60 значений.   -  person Adam Shaw    schedule 06.01.2018
comment
Возможно i1 <- seq_len(nrow(Name_Data)); percent(sapply(i1, function(i) RecordLinkage::levenshteinSim(names1[i], names2[setdiff(i1, i)])))   -  person akrun    schedule 06.01.2018
comment
percent(unlist(lapply(1:length(names1), function(x) levenshteinSim(names1[x], names2[-x])))) так будет немного быстрее   -  person erocoar    schedule 06.01.2018
comment
@erocoar, спасибо за помощь, но в соответствии с моим требованием я хочу проверить сходство и на основе идентификатора, в этом решении, если я где-то изменю идентификатор, скажем, последнее значение id2, с 10 на 2, это должно привести менее чем 56 записей, в настоящее время он дает всего 56 записей. Пожалуйста, предложите.   -  person Adam Shaw    schedule 06.01.2018
comment
@akrun, ценю ваши усилия, но, пожалуйста, помогите мне решить проблему на основе идентификатора здесь.   -  person Adam Shaw    schedule 06.01.2018
comment
@AdamShaw Возможно, outer может быть быстрее percent(outer(names1, names2, FUN= RecordLinkage::levenshteinSim)) или сделать перекрестное соединение library(data.table); CJ(names1, names2)[, percent(RecordLinkage::levenshteinSim(V1, V2))]   -  person akrun    schedule 06.01.2018
comment
@akrun, спасибо за более быстрое решение, но опять же, в соответствии с моим требованием, пожалуйста, предложите подход, который сначала проверяет пары клонов (id1,names1) и (id2,names2), исключает такие пары при вычислении, а затем, наконец, дает результат, по моему мнению, в общей сложности я должен получить здесь 60 записей. Спасибо.   -  person Adam Shaw    schedule 06.01.2018
comment
Извините, я не получаю 60 записей. По вашей логике может быть 56 за исключением того, который вы не сравниваете   -  person akrun    schedule 06.01.2018
comment
Бывают ли случаи, когда идентификатор один и тот же, но имя другое?   -  person erocoar    schedule 06.01.2018
comment
@erocoar, может быть, здесь я буду очень ясным, если каждая пара (id1,names1) имеет общую пару (id2,names2), я хочу исключить такие записи при вычислении%, остальное каждые (id1,names1) Pair необходимо сравнивать со всеми другими парами (id2,names2), а также, пожалуйста, избегайте использования циклов if или для достижения этого, спасибо.   -  person Adam Shaw    schedule 06.01.2018
comment
@akrun, пожалуйста, проверьте приведенные выше таблицы, значения имен1 и имена2 могут быть одинаковыми, но значения id1 и id2 делают их разными, я не хочу, чтобы сравнивались пары клонов, но разные пары, таким образом, если вы проверите здесь, Всего будет достигнуто 60 значений. Только первые 4 значения имен1 имеют клон в столбце имен2 на основе идентификатора   -  person Adam Shaw    schedule 06.01.2018


Ответы (1)


Не намного быстрее, но я бы предложил:

percent(unlist(lapply(1:length(names1), function(x) {
  levenshteinSim(names1[x], names2[!(names2==names1[x] & id2==id1[x])])})))

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

В качестве альтернативы это может быть быстрее - я думаю, это варьируется:

as.vector(t(1 - (stringdistmatrix(names1, names2, method = "lv") / 
         outer(nchar(names1), nchar(names2), pmax))))[unlist(lapply(1:length(names1), function(x) !(names2==names1[x] & id2==id1[x])))]
person erocoar    schedule 06.01.2018
comment
спасибо, однако, если что-то можно сделать, чтобы сделать скрипт быстрым, пожалуйста, помогите. - person Adam Shaw; 06.01.2018
comment
Вы можете ускорить его с помощью paste(round(unlist(lapply(1:length(names1), function(x) { levenshteinSim(names1[x], names2[!(names2t==names1t[x] & id2t==id1t[x])])}))*100, 1), "%", sep="") вместо вызова percent. Большая часть другого времени вычислений приходится на вызов levenshteinSim, где я не уверен, как его ускорить. - person erocoar; 06.01.2018