Array, vetor, join, regex ou %in%

Olá pessoal,

Estou com uma dúvida em relação a como fazer um match nas seguintes bases de dados de exemplo:

base_a <- tibble::tribble(
  ~nome_completo, 
  "fernanda kelly",   
  "leticia amor",  
  "beatriz da silva", 
  "ana de paula silva",
  "bruna barbosa", 
  "gustavo teles", 
  "amanda daniela souza"
)
base_b <- tibble::tribble(
  ~nome_incompleto, 
  "['colaboradores', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'nanda kelly']",   
  "['colaboradores', 'pesquisadora', 'beatriz', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'beatriz da silva']",  
  "['brunna barbosa', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'walter tomasi']", 
  "['colaboradores', 'gustavo telles', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'walter tomasi']",
  "['daniela sou', 'colaboradores', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'amanda teles']", 
  "['leticia amor', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico']",
  "['senhora', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'ana de paula']")

O que eu preciso?

Preciso que a base_a encontre seu match na base_b. Seja por sobrenome, nome completo ou somente primeiro nome. Não há uma variável chave pra fazer join, mas seria possível fazer join por array? Fiquei sem rumo nessa questão.

Alguém me ajuda?

Olá Fernanda

Cheguei a uma solução a qual não considero a ideal pois acredito que deveríamos usar regex (o que nos tomaria mais tempo)

Porém se a base não for tão extensa, acho que se pode considerar uma solução de mais brevidade:

base_a <- tibble::tribble(
  ~nome_completo,
  "fernanda kelly",
  "leticia amor",
  "beatriz da silva",
  "ana de paula silva",
  "bruna barbosa",
  "gustavo teles",
  "amanda daniela souza"
  )


base_b <- tibble::tribble(
  ~nome_incompleto, 
  "['colaboradores', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'nanda kelly']",   
  "['colaboradores', 'pesquisadora', 'beatriz', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'beatriz da silva']",  
  "['brunna barbosa', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'walter tomasi']", 
  "['colaboradores', 'gustavo telles', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'walter tomasi']",
  "['daniela sou', 'colaboradores', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'amanda teles']", 
  "['leticia amor', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico']",
  "['senhora', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'ana de paula']")




# Excluiremos os pronomes "da", "de, das, etc" senão muitas linhas irão casar
base_a$x <- 
  gsub(base_a$nome_completo, pattern = " da ", replacement = " ") |>
  gsub(pattern = " de ", replacement = " ") |> 
  # operador OU entre Nome/Sobrenome
  gsub(pattern = " ", replacement = "|")




lista <- as.list(NA)

for (i in 1:nrow(base_a)) {
  
 # armazenaremos o Nº das linhas que deram match
  j <- 
    grep(pattern = base_a[i,c('x')], base_b$nome_incompleto)

# Por fim unimos base_a à base_b  (linha à linha)
 lista[[i]]  <-
    cbind(
     base_a[i,1]
    ,base_b[j,]
    )
  
}


base_c <- 
  do.call(what = "rbind", lista)




# Contudo, repare que tivemos alguns casos com múltiplas associações. Elas ocorreram entre pessoas com o mesmo sobrenome. Para encontrarmos esses casos fazemos:

dplyr::filter(as.data.frame(table(base_c$nome_completo)), Freq > 1)
#>                 Var1 Freq
#> 1 ana de paula silva    2
#> 2      gustavo teles    2

Espero que atenda ao que precisa, Humberto

Created on 2023-06-05 with reprex v2.0.2

1 curtida

Olá,

Agradeço imensamente a sua resposta. Eu não manjo muito do assunto loopings. Foi um erro meu não trazer casos que não vão ter match. No mundo real o que mais vai acontecer é não dar match entre os nomes. Logo, usando o seu código na base real, tenho o retorno de erro exatamente por alguns nomes não darem match.

Um banco que não daria match é esse abaixo. Só acrescentei mais uma linha ali.

base_a <- tibble::tribble(
  ~nome_completo,
  "fernanda kelly",
  "leticia amor",
  "beatriz da silva",
  "ana de paula silva",
  "bruna barbosa",
  "gustavo teles",
  "amanda daniela souza",
  "Camila Bezerra")


base_b <- tibble::tribble(
  ~nome_incompleto, 
  "['colaboradores', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'nanda kelly']",   
  "['colaboradores', 'pesquisadora', 'beatriz', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'beatriz da silva']",  
  "['brunna barbosa', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'walter tomasi']", 
  "['colaboradores', 'gustavo telles', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'walter tomasi']",
  "['daniela sou', 'colaboradores', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'amanda teles']", 
  "['leticia amor', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico']",
  "['senhora', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'ana de paula']",
  "['senhora', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'jussara']")

Como seria agora?

Improvisei uma solução usando uma função do R base ainda desconhecida pra mim o identical(0)

base_a <- tibble::tribble(
  ~nome_completo,
  "fernanda kelly",
  "leticia amor",
  "beatriz da silva",
  "ana de paula silva",
  "bruna barbosa",
  "gustavo teles",
  "amanda daniela souza",
  "Camila Bezerra")


base_b <- tibble::tribble(
  ~nome_incompleto, 
  "['colaboradores', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'nanda kelly']",   
  "['colaboradores', 'pesquisadora', 'beatriz', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'beatriz da silva']",  
  "['brunna barbosa', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'walter tomasi']", 
  "['colaboradores', 'gustavo telles', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'walter tomasi']",
  "['daniela sou', 'colaboradores', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'amanda teles']", 
  "['leticia amor', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico']",
  "['senhora', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'ana de paula']",
  "['senhora', 'pesquisadora', 'cara', 'gente', 'estagiário', 'questionário', 'voluntários', 'senhor', 'médico', 'jussara']")





# Excluiremos os pronomes "da", "de, das, etc" senão muitas linhas irão casar
base_a$x <- 
  gsub(base_a$nome_completo, pattern = " da | de | das | dos ", replacement = " ") |>
# operador OU entre Nome/Sobrenome
  gsub(pattern = " ", replacement = "|")

# armazenaremos o resultado em uma lista
lista <- as.list(NA)

for (i in 1:nrow(base_a)) {
    
  if (identical(grep(pattern = base_a[i,c('x')], base_b$nome_incompleto), integer(0)) == FALSE) {
    
  
  
  # armazenaremos em "j" o índice das linhas que deram match
  j <- 
    grep(pattern = base_a[i,c('x')], base_b$nome_incompleto)
  
  # Por fim unimos base_a à base_b  (linha à linha)
  lista[[i]]  <-
    cbind(
      base_a[i,1]
      ,base_b[j,]
    )
  
  } else {
    
# as linhas que não casaram aparecerão no console
     print(paste(base_a[i,c('x')], "está sem match"))
    
  }
  
}
#> [1] "Camila|Bezerra está sem match"

# transformamos a lista em dataframe
base_c <- 
  do.call(what = "rbind", lista)




# Contudo, repare que tivemos alguns casos com múltiplas associações. Elas ocorreram entre pessoas com o mesmo sobrenome (Silva e Teles). Para encontrarmos esses casos fazemos:

dplyr::filter(as.data.frame(table(base_c$nome_completo)), Freq > 1)
#>                 Var1 Freq
#> 1 ana de paula silva    2
#> 2      gustavo teles    2

Created on 2023-06-07 with reprex v2.0.2

1 curtida

Não deu certo, mas clareou as ideias aqui. Vou usar sua ideia como base. Muito obrigada pela ajuda :)))

1 curtida