2

Я пытаюсь объединить два набора данных на основе столбца заголовка фильма, который содержит имена фильмов, используя нечеткое соответствие строк. Пример из 2 наборов данных приведен ниже.Нечеткие совпадения названий фильмов без использования цикла и выделения эквивалентных названий по дате выпуска

Первый набор данных выглядит

itemid userid rating  time        title release_date 
99995 1677 854  3 1997-12-22      sweet nothing   1995 
99996 1678 863  1 1998-03-07       mat' i syn   1997 
99997 1679 863  3 1998-03-07       b. monkey   1998 
99998 1429 863  2 1998-03-07      sliding doors   1998 
99999 1681 896  3 1998-02-11      you so crazy   1994 
100000 1682 916  3 1997-11-29 scream of stone (schrei aus stein)   1991 

Второй является

itemid userid rating  time      title release_date 
117201 3175936 9140  3 2013-09-22 bei tou zou de na wu nian   2013 
117202 3175936 17439  3 2013-09-18 bei tou zou de na wu nian   2013 
117203 3181128 3024  5 2013-09-13    mac & jack   2013 
117204 3181962 17310  5 2013-09-19   the last shepherd   2013 
117205 3188690 13551  5 2013-09-17  the making of a queen   2013 
117206 3198468 5338  3 2013-09-22   north 24 kaatham   2013 

dput - df1

structure(list(itemid = c(1677L, 1678L, 1679L, 1429L, 1681L, 
1682L), userid = c(854L, 863L, 863L, 863L, 896L, 916L), rating = c(3L, 
1L, 3L, 2L, 3L, 3L), time = structure(c(10217, 10292, 10292, 
10292, 10268, 10194), class = "Date"), title = c("sweet nothing", 
"mat' i syn", "b. monkey", "sliding doors", "you so crazy", "scream of stone (schrei aus stein)" 
), release_date = c("1995", "1997", "1998", "1998", "1994", "1991" 
)), .Names = c("itemid", "userid", "rating", "time", "title", 
"release_date"), row.names = 99995:100000, class = "data.frame") 

dput - df2

structure(list(itemid = c(3175936L, 3175936L, 3181128L, 3181962L, 
3188690L, 3198468L), userid = c(9140L, 17439L, 3024L, 17310L, 
13551L, 5338L), rating = c(3, 3, 5, 5, 5, 3), time = structure(c(15970, 
15966, 15961, 15967, 15965, 15970), class = "Date"), title = c("bei tou zou de na wu nian", 
"bei tou zou de na wu nian", "mac & jack", "the last shepherd", 
"the making of a queen", "north 24 kaatham"), release_date = c("2013", 
"2013", "2013", "2013", "2013", "2013")), .Names = c("itemid", 
"userid", "rating", "time", "title", "release_date"), row.names = 117201:117206, class = "data.frame") 
what I am looking forward to do is fuz 

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

Может ли кто-нибудь вести меня о том, как выполнить эту задачу?

Я попытался следующий код до сих пор:

df <- sapply(df1$title,lenvenshteinSim,df2$title) 

Это дает матрицу с размерами 11451 X 1682, где каждый столбец один название фильма от 1 кадра данных и строки содержат значение подобия. Я могу потенциально поставить петлю здесь или посмотреть на расплав & dcast, чтобы вытащить столбцы с max (similary)> 0.85, но это не выглядит эффективным способом. Кроме того, я не могу сопоставить дату выпуска в этом коде.

Любая помощь будет оценена по достоинству.

Спасибо.

+0

могли бы вы добавить вывод 'dput (DF)' для наборов данных к вопрос? –

+0

сделано. Хотя в данных нет соответствующих фильмов в образцах, но в реальном наборе данных есть соответствующие фильмы. например, если разрешить levenshtein-подобие> 0.80 и даты выпуска одинаковы - извлеките информацию в новый df – syebill

ответ

2

Вы можете объединить эти кадры данных

z <- merge(df1,df2,by='release_date',suffixes=c('.df1','.df2')) 

, который даст вам декартово произведение (т.е. все возможные комбинации между df1 и df2 для того же release_date, а затем вычислить расстояние Левенштейна по:

z$L.dist <- lenvenshteinSim(z$title.df1,z$title.df2) 

Имея z$L.dist, вы можете отфильтровать нужные строки:

subset(z,L.dist > 0.85) 

Update

Вот подобный подход с использованием data.table, что может быть более быстрой альтернативой:

library(data.table) 
d1 <- as.data.table(df1) 
d2 <- as.data.table(df2) 
setkey(d1,release_date) 
setkey(d2,release_date) 

z <- d1[d2,allow.cartesian=T,nomatch=F] 

#z[,L.dist:=lenvenshteinSim(title,i.title)] 
z[,L.dist:=mapply(lenvenshteinSim,title,i.title)] 


z[L.dist > 0.8] 
+0

. Ваш подход совершенно другой и очень хороший. Я хотел спросить, может ли это применяться к наборам данных с более чем 100K строк? – syebill

+0

Я собирался спросить вас об этом! :) Я думаю, что сам алгоритм должен быть достаточно эффективным, поэтому я бы предложил попробовать. –

+0

Я попробовал и придумал эту ошибку «Ошибка: не может выделить вектор размера 266.4 Мб Кроме того: Предупреждающие сообщения: 1: В' [.data.frame' (x, c (m $ xi, if (all .x) m $ x.alone), c (by.x, seq_len (ncx) [- by.x]),: Достигнуто общее выделение 5942Mb: см. справку (memory.size) 2: В '[. data.frame' (x, c (m $ xi, if (all.x) m $ x.alone), c (by.x, seq_len (ncx) [- by.x]),: Достигнуто полное распределение 5942Mb: см. Справку (memory.size) 3: В '[.data.frame' (x, c (m $ xi, if (all.x) m $ x.alone), c (by.x, seq_len (ncx) [- by.x]): Достигнуто полное выделение 5942Mb: см. справку (memory.size) – syebill