3
votes

Correspondance des colonnes dans 2 blocs de données lorsque les nombres ne correspondent pas exactement

Comment faire correspondre deux blocs de données différents lorsque les valeurs que je compare ne sont pas exactement les mêmes?

Je pensais utiliser merge () mais je ne suis pas sûr. p >

Tableau1:

ID           Value.2
10001        a
18274        b
12826        c
10289        u

Tableau2:

ID           Value.1
10001        x
18273-9      y
12824/5/6/7  z
10283/5/9    d

Comment fusionner les tableaux 1 et 2 en fonction de l'ID?

Quelle fonction spécifique du package fuzzyjoin utiliserais-je, en particulier avec les cas "/" & "-"? Comment étendre le cas "-" de 18273-9 pour que R enregistre 18273/18274/18275 / ...?


3 commentaires

Découvrez le package fuzzyjoin .


Copie possible de Rejoindre deux ensembles de données en utilisant la logique floue


Quel type de jointure (intérieure, gauche, complète) recherchez-vous? Quel est votre résultat attendu?


3 Réponses :


0
votes

Vous pouvez utiliser la fonction de correspondance de chaîne floue "consentp" de la base R.

df1 <- data.frame(ID=c("10001","18273-9","12824/5/6/7","10283/5/9"), 
                  value=c("a","c","d","k"))

df2 <- data.frame(ID=c("10001","18274","12826","10289"), 
                  value=c("o","p","q","r"))

apply(df1, 1, function(x) agrep(x["ID"], df2$ID, max = 3.5))

Comme vous le voyez, il a du mal à trouver la correspondance pour la ligne 4. Il peut donc être judicieux de nettoyer votre ID variable (par exemple, retirez le "/") avant d'exécuter accord.


0 commentaires

0
votes

Une option pourrait consister à extraire le format de l'identifiant que vous souhaitez conserver. Et puis faites votre fusion.

Vous pouvez formater votre colonne ID comme suit:

Table1 %>% mutate(ID = str_extract("[0-9]{5}"))

Si vous ne voulez que les chiffres avant les symboles

Table1 %>% mutate(ID = str_extract("[0-9]*")) 

Si vous souhaitez conserver la première séquence de 5 chiffres

library(stringr) 
library(dplyr) 

Ceci répond à votre deuxième question, mais n'utilise pas le package fuzzyjoin p >


0 commentaires

1
votes

Vous pouvez écrire une fonction pour extraire les séquences correspondantes des chaînes contenant "/" ou "-" et les recombiner dans un nouveau data.frame comme suit:

merge(doIt(df1), df2, by = "ID", all.x = T)

Ensuite, vous pouvez fusionnez les df2 et df1:

df1 <- data.frame(ID=c("10001","18273-9","15273-8", "15170-4",  "12824/5/6/7","10283/5/9"), 
                  value=c("a","c","c", "d","k", "l"), stringsAsFactors = F)

df2 <- data.frame(ID=c("10001","18274","12826","10289"), 
                  value=c("o","p","q","r"), stringsAsFactors = F)

doIt <- function(df){
  listAsDF <- function(l) {
    x <- stack(setNames(l, temp$value))
    names(x) <- c("ID", "value")
    return(x)
  }
  Base <- df[!grepl("\\/", df$ID) & !grepl("\\-", df$ID), ]
  #1 cases when - present
  temp <- df[grep("\\-", df$ID),]
  temp <- listAsDF(lapply(strsplit(temp$ID, "-"), function(e) seq(e[1], paste0(strtrim(e[1], nchar(e[1])-1), e[2]), 1)))
  Base <- rbind(Base, temp)
  #2 cases when / present
  temp <- df[grep("\\/", df$ID),]
  temp <- listAsDF(lapply(strsplit(temp$ID, "/"), function(a) c(a[1], paste0(strtrim(a[1], nchar(a[1])-1), a[-1]))))
  Base <- rbind(Base, temp)
  return(Base)
}

J'espère que cela vous aidera!


4 commentaires

Cela a été vraiment utile! Puis-je savoir pourquoi vous utilisez setNames avec x et temp? Je vous remercie!


setNames donne des noms à un objet et renvoie l'objet lui-même, c'est ce que je voulais car j'ai besoin des noms plus loin dans la fonction de pile.


Cela vous dérange-t-il également d'expliquer les arguments dans strtrim ? Je l'ai googlé et il n'y en a que deux - strtrim (x, width) ? Merci beaucoup!! Désolé de vous avoir dérangé, je ne fais que commencer.


strtrim coupe une chaîne à la largeur désirée, comme vous dites que cela prend deux arguments, si vous démontez le code, vous voyez, c'est exactement ce qui se passe. x est e [1] / a [1] et width est nchar (e [1 ]) - 1 / nchar (a [1]) - 1