stringdist_semi_join показывает только столбцы из dataframe1

У меня есть два фрейма данных:

df1 <- data.frame(City=c("Munchen_Paris","Munchen_Paris","Barcelona_Milan", "Londen_Dublin","Madrid_Malaga"), 
                  value1=c(11,21,33,2,53))

df2 <- data.frame(City=c("Munnich_Parijs","Barcelona_Munster","Barcelona_Milan","London_Dub","London_Oxford","Pisa_Luik"), 
                  value2=c(22,2,44,54,29,65))

Я пытаюсь объединить эти кадры данных с помощью fuzzyjoin.

Результат, который я ищу:

           City.x  value1   City.y             value2  string_distance
1   Munchen_Paris      11   Munnich_Parijs     22      5
2   Munchen_Paris      21   Munnich_Parijs     22      5
3 Barcelona_Milan      33   Barcelona_Milan    44      0
4   Londen_Dublin       2   London_Dub         54      4

(для каждой строки в df1 с совпадением в df2 для City с string_distance ‹ 9 мне нужна строка в новой таблице, содержащая все столбцы из df1 и df2 с наименьшим string_distance) Когда я делаю:

df3 <- stringdist_semi_join(df1, df2, by = "City", max_dist = 9, distance_col = "string_distance")

Я получаю только эти столбцы:

> df3
             City value1
1   Munchen_Paris     11
2   Munchen_Paris     21
3 Barcelona_Milan     33
4   Londen_Dublin      2

Если я делаю полное соединение, я получаю это:

> df3 <- stringdist_full_join(df1, df2, by = "City", max_dist = 9, distance_col = "string_distance")

> df3
           City.x value1            City.y value2 string_distance
1   Munchen_Paris     11    Munnich_Parijs     22               5
2   Munchen_Paris     21    Munnich_Parijs     22               5
3 Barcelona_Milan     33 Barcelona_Munster      2               6
4 Barcelona_Milan     33   Barcelona_Milan     44               0
5   Londen_Dublin      2        London_Dub     54               4
6   Londen_Dublin      2     London_Oxford     29               7
7   Madrid_Malaga     53              <NA>     NA              NA
8            <NA>     NA         Pisa_Luik     65              NA

Я могу удалить строки, содержащие NA и group_by City.x, хотя тогда я потеряю одну из первых двух строк.

Если я делаю inner_join, я получаю это:

    df3 <- stringdist_inner_join(df1, df2, by = "City", max_dist = 9, distance_col = "string_distance")

df3

> df3
           City.x value1            City.y value2 string_distance
1   Munchen_Paris     11    Munnich_Parijs     22               5
2   Munchen_Paris     21    Munnich_Parijs     22               5
3 Barcelona_Milan     33 Barcelona_Munster      2               6
4 Barcelona_Milan     33   Barcelona_Milan     44               0
5   Londen_Dublin      2        London_Dub     54               4
6   Londen_Dublin      2     London_Oxford     29               7

Странно, что stringdist_semi_join не показывает столбцы df2? Есть ли другой способ достичь результата, который я ищу в первой таблице выше?

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


person user2165379    schedule 10.04.2020    source источник


Ответы (1)


Что делает полусоединение (из документации dplyr):

вернуть все строки из x, где есть совпадающие значения в y, сохраняя только столбцы из x. Полусоединение отличается от внутреннего соединения тем, что внутреннее соединение будет возвращать одну строку x для каждой совпадающей строки y, где полусоединение никогда не будет дублировать строки x.

Таким образом, поведение, которое вы видите, ожидаемо.

Вы ищете внутреннее соединение:

вернуть все строки из x, где есть совпадающие значения в y, и все столбцы из x и y. Если между x и y имеется несколько совпадений, возвращаются все комбинации совпадений.

В fuzzyjoin это называется stringdist_inner_join:

df3 <- stringdist_inner_join(df1, df2, by = "City", max_dist = 9, distance_col = "string_distance")
person Bas    schedule 10.04.2020
comment
@ Бас Спасибо! Хотя я не был достаточно ясен в своем вопросе (я изменил свой вопрос и добавил вывод inner_join). Я ищу только лучшее совпадение в df2 (только совпадение с наименьшим string_distance) для каждой строки в df1. Полуобъединение делает это, хотя и не предоставляет столбцы из df2. - person user2165379; 10.04.2020
comment
Полусоединение сохраняет только те строки df1, которые совпадают. Он не ищет «лучшее совпадение». Насколько я знаю, невозможно добиться того, чего вы хотите, только с помощью соединения. Я бы придерживался inner_join и отфильтровывал наименьшее значение distance_col для каждого City.x. - person Bas; 11.04.2020
comment
@ Бас. Спасибо за вашу помощь. Я придерживался inner_join и добавил столбец с номером строки в качестве идентификатора. Затем я добавил этот фильтр df3 %›% dplyr::group_by(id.x) %›% slice(what.min(string_distance)). - person user2165379; 11.04.2020