IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Correlation de chaine de caracteres


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2009
    Messages : 139
    Par défaut Correlation de chaine de caracteres
    Bonjour a tous,

    Alors voila je me retrouve a devoir filer un coup de main a un membre de ma famille et a mettre de l'ordre dans ses fichiers clients qui sont une aberation. Il y a plusieurs feuilles CSV qui contiennent toutes des donnees et j'essaye de faire un tri dans tout ca. Bien entendu elles ont ete remplie n'importe comment .Il n'y a pas de format unique,certains clients sont dans plusieurs feuilles a la fois et toutes les informations ont ete saisie a la main avec un taux d'erreur important.
    Voila pour la situation de depart.

    Maintenant voila ma question. Je cherche a eviter les doublons. Malheureusement, je ne peux pas me permettre de faire uniquement un test sur le prenom/Nom de famille. En effet, vu comment les donnes ont ete rentre je peux tres bien avoir 3 entrees client differents de la maniere suivante:

    Barry Hiland 6 Morgan Street
    Barry+Helen Hiland 6 Morgan St
    Barry Hilano 6 Mojan St

    On peut voir que la deuxieme entree contient le prenom de la femme
    la troisieme contient une faute d'orthographe dans le nom de famille ainsi que dans le nom de la rue
    La premiere ligne contient 'Street' en entier alors que les deux autres ont l'abrege 'St'.

    Or il s'agit du meme client. Je souhaite donc pouvoir mettre au point un test de correlation entre ces differentes chaines qui se ressemble pas mal quand meme, et donc le PC serait capable de voir qu'il s'agit de la meme personne.

    J'avoue que ca ne me parait pas evident donc si qlq avait la moindre idee...

    Julien

    PS: Dsl pour les accents et fautes de frappe mais les qwerty...

  2. #2
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Ça, c'est un beau problème...

    A mon avis, il ne faut pas chercher à faire ça d'un seul coup: en fonction des principaux types d'erreurs, il faut définir plusieurs étapes pour réduire progressivement le désordre des listes.

    Il y a plusieurs étapes qui concerneront les lignes entières (une chaine par ligne), et plusieurs étapes qui concerneront les lignes déjà décomposées en champs (une liste de chaines par ligne).

    Pour chaque étape, il me semble inévitable de recourir aux expressions régulières. C'est très puissant, mais ça ressemble souvent à une 'punition'...

    Au minimum, on peut utiliser le module fnmatch (qui utilise les expressions régulières en interne), construit pour permettre les recherches de noms de fichiers avec:
    '?'=n'importe quel caractère,
    '*'=n'importe quel groupe de caractères éventuellement vide
    [xyz]=liste des caractères possibles pour une position
    [!xyz]=liste des caractères interdits pour une position

    Pour utiliser le module fnmatch dans la recherche de chaines normales, il ne faut pas utiliser la fonction fnmatch qui normalise les chemins des disques, mais fnmatchcase.

    Voilà un exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    from fnmatch import fnmatchcase as trouve
     
    L = ["Barry Hiland 6 Morgan Street",
    "Barry+Helen Hiland 6 Morgan St",
    "Barry Hilano 6 Mojan St"]
     
    motif = "Barry*Hilan[do]*St*"
    for ligne in L:
        if trouve(ligne,motif):
            print ligne
    Barry Hiland 6 Morgan Street
    Barry+Helen Hiland 6 Morgan St
    Barry Hilano 6 Mojan St
    A voir aussi s'il est nécessaire de neutraliser la casse (majuscule/minuscule), voire, mais c'est plus compliqué, les caractères accentués et autres signes diacritiques ('ç', ...).

    Bon courage!

    Tyrtamos

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    139
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2009
    Messages : 139
    Par défaut
    Hello,
    Merci tyrtamos, ca pourrai etre une solution. mais j'avais envisage les choses sous cet angle la:

    Pour deux chaine : chaine_1,chaine_2 on calcul un 'coeff de correlation'
    Si coefficient de corellation>90% -> c'est la meme chaine
    Si 60%<coefficient de corellation<90% -> On demande a l'utilisateur de chosir si c'est la meme chaine ou pas
    Si coefficient de corellation<60% -> la chaine est differente>

    Bien entendu mes bornes 60% et 90% sont la a titre d'example.

    Maintenant il reste a trouver comment comment trouver une corellation.
    Voici un exemple auque j'ai pense, mais c'est pas performant
    En gros on calcul la lettre moyenne de la chaine
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    chaine=[chaine_1,chaine_2]
    moyenne=[]
    for element in chaine:
        for c in element :
            total=total+ord(c)
        moyenne.append(total/len(chaine_1))
     
    coeff=moyenne[1]-moyenne[0]
    Enfin bon ca c'est un peu simplet comme idee. je me demande si il n'y a pas des algo connu performant...

  4. #4
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    bonjour,

    les moteurs de recherche sur le web savent faire ceci puisqu'en rentrant une requête mal orthographiée ils arrivent tout de même à trouver la bonne page

    je ne sais pas la techno qui est en jeu, mais peut être que le module reverand pourrait t'aider (c'est un classificateur bayésien)

    à mon avis, si tu veux quelque chose de robuste, je te conseille de rechercher sur le net plutôt que de recoder

  5. #5
    Membre expérimenté
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    159
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 159
    Par défaut
    Salut,

    Peut-être que difflib.SequenceMatcher (http://docs.python.org/library/diffl...atcher-objects) et notamment la méthode ratio() peuvent suffire ?

  6. #6
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    tiens je connaissais pas ce module, c'est sympa. Je me suis amusé à essayer:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> from difflib import SequenceMatcher as Matcher
    >>> s = Matcher(None, "Barry Hilano", "Barry Hiland")
    >>> s.ratio()
    0.91666666666666663
    >>> s = Matcher(None, "Barry Hilano", "Hilary Barno")
    >>> s.ratio()
    0.5
    >>> s = Matcher(None, "Barry Hiland 6 Morgan Street", "Barry Hilano 6 Mojan St")
    >>> s.ratio()
    0.82352941176470584
    je pense que c'est ça qu'il te faut :p

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 9
    Dernier message: 06/11/2007, 12h36
  2. Réponses: 13
    Dernier message: 13/06/2003, 14h13
  3. Pb Update avec chaine de caractere
    Par JuJu° dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 28/05/2003, 15h58
  4. [LG]comparaison de chaines de caracteres
    Par thesam dans le forum Langage
    Réponses: 6
    Dernier message: 20/05/2003, 22h41
  5. Probleme sur les chaines de caractere
    Par scorpiwolf dans le forum C
    Réponses: 8
    Dernier message: 06/05/2002, 19h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo