Fusion de deux bases de données utilisant une correspondance floue/approximative des chaînes de caractères dans R

DESCRIPTION

j'ai deux ensembles de données avec des informations que je dois fusionner. Les seuls champs communs que j'AI sont des cordes qui ne correspondent pas parfaitement et un champ numérique qui peut être substantiellement différent

La seule façon d'expliquer le problème, c'est de vous montrer les données. un.csv et b.csv. Je suis en train de fusion de B à A.

il y a trois champs en B et quatre en A. nom de la société (dossier A Seulement), le nom du fonds, la catégorie d'actif et L'actif. Jusqu'à présent, je me suis concentré sur la correspondance des noms de fonds en remplaçant des mots ou des parties des chaînes de caractères pour créer des Correspondances exactes, puis en utilisant:

a <- read.table(file = "http://bertelsen.ca/R/a.csv",header=TRUE, sep=",", na.strings=F, strip.white=T, blank.lines.skip=F, stringsAsFactors=T) 
b <- read.table(file = "http://bertelsen.ca/R/b.csv",header=TRUE, sep=",", na.strings=F, strip.white=T, blank.lines.skip=F, stringsAsFactors=T)
merge(a,b, by="Fund.Name") 

cependant, cela ne m'amène qu'à environ 30% de correspondance. Le reste, je dois le faire à la main.

actif est un champ numérique qui n'est pas toujours correct dans l'un ou l'autre et peut varier fortement si le fonds a de faibles actifs. Catégorie d'actif est un champ de chaîne de caractères qui est "généralement" le même dans les deux fichiers, cependant, il y a des divergences.

A la complication s'ajoutent les différentes séries de fonds, dans le fichier B. Par exemple:

AGF valeur canadienne

AGF valeur canadienne-D

Dans ces cas, j'ai à choisir celui qui n'est pas seried, ou choisir celui qui est appelé "Un", " -", ou "Conseiller" comme le match.

QUESTION

Quelle est selon vous la meilleure approche? Cet exercice est quelque chose que je dois faire sur une base mensuelle et l'appariement manuel est incroyablement long. Des exemples de code seraient utiles.

IDEAS

une méthode qui, je pense, peut fonctionner est la normalisation des chaînes basées sur la première lettre capitalisée de chaque mot dans la chaîne. Mais je n'ai pas été capable de trouver comment faire avec R.

une autre méthode que j'ai considérée était la création d'un index des correspondances basé sur une combinaison d'actifs, Nom du fonds, Catégorie d'actifs et société. Mais encore une fois, je ne sais pas comment faire avec R. ou, d'ailleurs, si c'est possible.

Les exemples de code, de commentaires, de pensées et de direction sont grandement appréciés!

13
demandé sur pnuts 2010-02-09 22:41:38

4 réponses

la correspondance approximative des chaînes de caractères n'est pas une bonne idée car une correspondance incorrecte invaliderait toute l'analyse. Si les noms de chaque source sont les mêmes à chaque fois, alors la construction des index semble la meilleure option pour moi aussi. Cela se fait facilement dans R:

supposons que vous ayez les données:

a<-data.frame(name=c('Ace','Bayes'),price=c(10,13))
b<-data.frame(name=c('Ace Co.','Bayes Inc.'),qty=c(9,99))

construisez un index de noms pour chaque source Une fois, peut-être en utilisant pmatch etc. comme point de départ, puis validation manuelle.

a.idx<-data.frame(name=c('Ace','Bayes'),idx=c(1,2))
b.idx<-data.frame(name=c('Ace Co.','Bayes Inc.'), idx=c(1,2))

puis pour chaque course de fusion à l'aide de:

a.rich<-merge(a,a.idx,by="name")
b.rich<-merge(b,b.idx,by="name")
merge(a.rich,b.rich,by="idx")

ce Qui nous donnerait:

  idx name.x price     name.y qty
1   1    Ace    10    Ace Co.   9
2   2  Bayes    13 Bayes Inc.  99
2
répondu Jyotirmoy Bhattacharya 2010-02-10 04:13:38

Il est fortement recommandé d'utiliser le dgrtwo/fuzzyjoin paquet. stringdist_inner_join(a,b, by="Fund.Name")

11
répondu user3808394 2016-07-07 13:36:37

une suggestion rapide: essayez de faire quelques correspondances sur les différents champs séparément avant d'utiliser merge. L'approche la plus simple est avec l' pmatch fonction, bien que R ne manque pas de fonctions d'appariement de texte (par exemple agrep). Voici un exemple simple:

pmatch(c("med", "mod"), c("mean", "median", "mode"))

Pour votre jeu de données, cela correspond à tous les fonds de noms de a:

> nrow(merge(a,b,x.by="Fund.Name", y.by="Fund.name"))
[1] 58
> length(which(!is.na(pmatch(a$Fund.Name, b$Fund.name))))
[1] 238

une fois que vous créez des correspondances, vous pouvez facilement les fusionner en utilisant celles-ci à la place.

8
répondu Shane 2010-02-09 21:08:37

je suis de la section locale du Canada et je reconnais les noms des fonds.

C'est une question difficile car chacun des fournisseurs de données choisit son propre formulaire pour l'individu noms de fonds. Certains utilisent une structure différente comme tous les extrémité dans L'un ou L'autre fonds ou classe d'autres sont partout. Chacun semble choisir leur propre court-formes qui évoluent régulièrement.

C'est pourquoi tant de gens comme vous le faites à la main sur une base régulière. Certaines firmes de consultation en faire la liste des index pour relier diverses sources, vous ne savez pas si vous avez exploré cette voie?

comme Shane et Marek l'ont fait remarquer, il s'agit d'une tâche qui va plus loin qu'une simple jointure. De nombreuses entreprises sont aux prises avec ce problème. Je suis au milieu de mes travaux sur ce...

Jay

1
répondu Jay 2010-02-09 21:11:23