如何检查第一个数据帧中的值是否包含或与另一个数据帧中的值匹配

use*_*007 8 string r dplyr partial-matches

我正在使用R一些数据框。我的问题与如何检查第一个数据帧中的变量值是否与另一个数据帧中的值匹配有关。merge该匹配与或 之类的匹配非常不同join。我将介绍我的数据框(dput()最后):

我的第一个数据框是df1. name它包含我想与第二个数据帧中的其他变量进行对比的变量。它看起来像这样:

df1
                   name
1            JUAN GIRON
2            GINA OLEAS
3 JUAN FERNANDO ELIZAGA
4          MARCO TORRES
5   JUAN PABLO GONZALEZ
6            IRMA GOMEZ
Run Code Online (Sandbox Code Playgroud)

第二个数据框是df2. 它还包含一个变量name,用于与namefrom进行对比df1。它看起来像这样(在实际情况中df2可能非常大,超过 1000 行):

df2
                      name val
1            JUANA MARQUEZ   1
2         FERNANDO ELIZAGA   2
3               IRMA GOMEZ   3
4           PABLO GONZALEZ   4
5               GINA LUCIO   5
6              MARK TORRES   6
7           LETICIA BLACIO   7
8 JUAN PABLO GIRON BELTRAN   8
Run Code Online (Sandbox Code Playgroud)

我正在寻找一种方法来检查df1forname变量的每一行是否包含或与namein的任何值匹配df2。例如,JUAN GIRON使用namefrom检查后的值df2应该返回,给出值 ,yes因为它包含在字符串JUAN PABLO GIRON BELTRANfrom中df2。同样的情况也适用于其他值。最后我想要这样的东西:

df3
                   name val
1            JUAN GIRON yes
2            GINA OLEAS  no
3 JUAN FERNANDO ELIZAGA yes
4          MARCO TORRES  no
5   JUAN PABLO GONZALEZ yes
6            IRMA GOMEZ yes 
Run Code Online (Sandbox Code Playgroud)

我怎样才能达到这个结果?我尝试过grepl()使用连接字符串|,但它不起作用,因为某些值yes在不匹配时返回匹配。

另外,由于数据可能很大,我希望有一个解决方案dplyr,因为比较是按行进行的,所以速度可能很慢。或者欢迎任何快速解决方案。非常感谢!

接下来是数据:

#df1
df1 <- structure(list(name = c("JUAN GIRON", "GINA OLEAS", "JUAN FERNANDO ELIZAGA", 
"MARCO TORRES", "JUAN PABLO GONZALEZ", "IRMA GOMEZ")), row.names = c(NA, 
-6L), class = "data.frame")

#df2
df2 <- structure(list(name = c("JUANA MARQUEZ", "FERNANDO ELIZAGA", 
"IRMA GOMEZ", "PABLO GONZALEZ", "GINA LUCIO", "MARK TORRES", 
"LETICIA BLACIO", "JUAN PABLO GIRON BELTRAN"), val = 1:8), row.names = c(NA, 
-8L), class = "data.frame")
Run Code Online (Sandbox Code Playgroud)

Tho*_*ing 5

也许我们可以这样做

df1 %>%
    mutate(val = c("no", "yes")[1 + (rowSums(
        outer(
            strsplit(name, "\\s+"),
            strsplit(df2$name, "\\s+"),
            Vectorize(function(x, y) all(x %in% y) | all(y %in% x))
        )
    ) > 0)])
Run Code Online (Sandbox Code Playgroud)

这使

                   name val
1            JUAN GIRON yes
2            GINA OLEAS  no
3 JUAN FERNANDO ELIZAGA yes
4          MARCO TORRES  no
5   JUAN PABLO GONZALEZ yes
6            IRMA GOMEZ yes
Run Code Online (Sandbox Code Playgroud)


Ska*_*qqs 3

这是一种使用正则表达式模式并处理长度为 2 或 3 的名称的方法。还有改进的空间,我很想阅读这个问题的其他答案。

# Input
a <- strsplit(df2$name, " ")
# Output
b <- c()

# Define regex pattern
for(i in 1:length(a)){
  if(length(a[[i]]) == 3){
    temp <- paste0(
        a[[i]][1], " ", a[[i]][2], "|",
        a[[i]][1], " ", a[[i]][3], "|",
        a[[i]][2], " ", a[[i]][3])
  } else if(length(a[[i]] == 2)){
    temp <- paste(a[[i]], collapse = " ")
  } else {
    stop("Length of split name was not 2 or 3")
  }
  b <- c(b, temp)
}

df1$val <- grepl(paste(b, collapse = "|"), df1$name)
Run Code Online (Sandbox Code Playgroud)

或者,在b使用上面的循环定义之后:

library(dplyr)
patt <- paste(b, collapse = "|")
df1 %>%
    mutate(val = grepl(patt, name))
Run Code Online (Sandbox Code Playgroud)

结果:

> df1
                   name    val
1            JUAN GIRON    TRUE
2            GINA OLEAS   FALSE
3 JUAN FERNANDO ELIZAGA    TRUE
4          MARCO TORRES   FALSE
5   JUAN PABLO GONZALEZ    TRUE
6            IRMA GOMEZ    TRUE
Run Code Online (Sandbox Code Playgroud)