R - 使用 grepl 的条件模式匹配

R - conditional pattern matching using grepl

我有两个数据框,像这样:

name <- c("joe", "kim", "kerry", "david")
name2 <- c("kim", "david", "joe", "kerry")
school <- c("cambridge", "south carolina", "vermont binghamton", "delaware")
school2 <- c("south carolina", "delaware", "cambridge magdalene", "vermont")

df1 <- data.frame(name, school)
df2 <- data.frame(name2, school2)

我想做的是:

  1. df2$name2 中搜索 df1$name 中的匹配项。
  2. 如果找到匹配项,请比较匹配行中的 df2$school2df1$school
  3. 如果在 df1$school 中找不到 df2$school2 的匹配项,df2$perfect.match
  4. 列中的 return FALSE

例如,由于 df2 中的 "joe" 与 df1 中的 "joe" 相匹配,因此存在匹配。但是,由于两者中 "school" 的值不同,因此 df2 中第三行的值为 FALSE 的列。 df2.

中的第 4 行相同

我试过使用 grep 和 grepl。我认为 grepl 是最好的,因为它 return 是一个逻辑值。我试过的是:

df2$perfect.match <- ifelse(grepl(paste(df2$name2, collapse = "|"), 
df1$name, fixed = F) & grepl(paste(df2$school2, collapse = "|"), df1$school, fixed = F), "", "FALSE")

然而,我得到的只是:

  name2             school2 perfect.match
1   kim      south carolina         FALSE
2 david            delaware              
3   joe cambridge magdalene              
4 kerry             vermont 

当我想要的结果是:

  df2

  name2             school2 perfect.match
1   kim      south carolina         
2 david            delaware              
3   joe cambridge magdalene         FALSE     
4 kerry             vermont         FALSE

如果可以的话,最好快点。真正的数据框非常大。谢谢。

更新:

我还希望能够强制 df2$school 的行具有与 df1$school 中对应的 name 匹配项相同的值,就像这样:

  name2             school2
1   kim      south carolina
2 david            delaware
3   joe           cambridge 
4 kerry   vermont binghamton

你可以做...

df2$perfect.match <- paste(df2$name2, df2$school2) %in% paste(df1$name, df1$school)

df2
  name2             school2 perfect.match
1   kim      south carolina          TRUE
2 david            delaware          TRUE
3   joe cambridge magdalene         FALSE
4 kerry             vermont         FALSE

比将列粘贴在一起稍微快一些:

matches <- df2$name2 %in% df1$name
df2$perfect.match <- df2$school2[matches] %in% df1$school

microbenchmark::microbenchmark(
  v1 = {matches <- df2$name2 %in% df1$name
  df2$perfect.match <- df2$school2[matches] %in% df1$school
  },
  v2 = {df2$perfect.match <- paste(df2$name2, df2$school2) %in% paste(df1$name, df1$school)}
)

使用dplyr,您可以:

dfX <- df1 %>%
  bind_rows(.,df2) %>%
  group_by(name) %>%
  distinct(school) %>%
  count(name, name = "perfect.matched") %>% 
  left_join(df2,.,by = 'name') %>%
  mutate(., perfect.matched = ifelse(perfect.matched ==1,"","FALSE"))

并获得以下输出:

> dfX
   name              school perfect.matched
1   kim      south carolina                
2 david            delaware                
3   joe cambridge magdalene           FALSE
4 kerry             vermont           FALSE

我们可以使用 match%in%grepl 不会在这里,因为这是精确匹配而不是模式匹配。

df2$perfect_match <- df2$school2 %in% df1$school[match(df2$name2, df1$name)]
df2
#  name2             school2 perfect_match
#1   kim      south carolina          TRUE
#2 david            delaware          TRUE
#3   joe cambridge magdalene         FALSE
#4 kerry             vermont         FALSE