连接R中的 Dataframe ,匹配字符串中的模式

v64noz0r  于 2023-02-01  发布在  其他
关注(0)|答案(3)|浏览(145)

两张真实的生活中的大table要连接起来,但这里有一个小的reprex:
我有一个小字符串的表,我想在第二个表上进行左连接,连接的基础是这些小字符串是否可以在第二个表上的大字符串中找到。

df_1 <- data.frame(index = 1:5,
                   keyword = c("john", "ella", "mil", "nin", "billi"))

df_2 <- data.frame(index_2 = 1001:1008,
                   name = c("John Coltrane", "Ella Fitzgerald", "Miles Davis", "Billie Holliday", 
                            "Nina Simone", "Bob Smith", "John Brown", "Tony Montana"))

df_results_i_want <- data.frame(index = c(1, 1:5),
                                keyword = c("john", "john", "ella", "mil", "nin", "billi"),
                                index_2 = c(1001, 1007, 1002, 1003, 1005, 1004),
                                name    = c("John Coltrane", "John Brown", "Ella Fitzgerald", 
                                            "Miles Davis", "Nina Simone", "Billie Holliday"))

看起来str_detect()调用和left_join()调用可能是解决方案的一部分-即我希望这样的东西:

library(tidyverse)

df_results <- df_1 |> left_join(df_2, join_by(blah blah str_detect() blah blah))

我使用dplyr 1.1,所以我可以使用join_by(),但我不知道正确的方式来获得我所需要的-有人能帮助吗?
我想我可以使用tidyr::crossing()执行一个简单的交叉连接,然后再执行str_detect()操作(并过滤掉不匹配的内容)

df_results <- df_1 |>
  crossing(df_2) |>
  mutate(match = str_detect(name, fixed(keyword, ignore_case = TRUE))) |>
  filter(match) |>
  select(-match)

但在我的真实的例子中,交叉连接将产生一个绝对巨大的表,它将淹没我的PC。
谢谢你。

y0u0uwnf

y0u0uwnf1#

您可以尝试fuzzy_join::regex_join()

library(fuzzyjoin)
regex_join(df_2, df_1, by=c("name"="keyword"), ignore_case=T)

输出:

index.x            name index.y keyword
1    1001   John Coltrane       1    john
2    1002 Ella Fitzgerald       2    ella
3    1003     Miles Davis       3     mil
4    1004 Billie Holliday       5   billi
5    1005     Nina Simone       4     nin
6    1007      John Brown       1    john
w46czmvw

w46czmvw2#

join_by不支持不精确连接(但不相等),但可以使用fuzzyjoin

library(dplyr)
library(fuzzyjoin)
df_2 %>% 
  mutate(name = tolower(name)) %>% 
  fuzzy_left_join(df_1, ., by = c(keyword = "name"), 
                  match_fun = \(x, y) str_detect(y, x))

  index keyword index_2            name
1     1    john    1001   john coltrane
2     1    john    1007      john brown
3     2    ella    1002 ella fitzgerald
4     3     mil    1003     miles davis
5     4     nin    1005     nina simone
6     5   billi    1004 billie holliday
lnvxswe2

lnvxswe23#

我们可以使用SQL来实现这一点。

library(sqldf)

sqldf("select * from [df_1] A
  left join [df_2] B on B.name like '%' || A.keyword || '%'")

给出:

index keyword index_2            name
1     1    john    1001   John Coltrane
2     1    john    1007      John Brown
3     2    ella    1002 Ella Fitzgerald
4     3     mil    1003     Miles Davis
5     4     nin    1005     Nina Simone
6     5   billi    1004 Billie Holliday

它可以放置在管道中,如下所示:

library(magrittr)
library(sqldf)

df_1 %>%
  { sqldf("select * from [.] A
      left join [df_2] B on B.name like '%' || A.keyword || '%'")
  }

相关问题