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 Réponses :
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.
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 >
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!
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
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?