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

Calcul scientifique Python Discussion :

extraction de données d'un fichier texte


Sujet :

Calcul scientifique Python

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 5
    Points : 2
    Points
    2
    Par défaut extraction de données d'un fichier texte
    Bonjour,
    C'est ma première tentative d'utiliser Python à la place du shell (awk).

    J'ai un fichier de plusieurs milliers de lignes, organisé en six champs, tous numériques ($1 => $6) séparés par une tabulation (\t). La première ligne peut comporter les noms des champs si ça aide.

    j'aimerais faire ce qui suit...

    - parcourir le fichier ligne par ligne (readline) et récupérer le contenu de la ligne qui vient d'être lue dans une structure adéquate, car il faut travailler sur les champs, indépendamment les uns des autres. Je ne sais pas quoi choisir d'ailleurs...

    - lecture ligne 1: stocker le contenu des champs ($1) ($4) et($6) dans trois variables (entity, sigma1, sigma2) et initialiser un compteur (cpt=1)
    - tant que $1 (entity) ne change pas, lire la ligne suivante, incrémenter le compteur (cpt = cpt + 1) et ajouter $4 à sigma1 et $6 à sigma2

    ... ainsi de suite, tant que $1 (entity) n'a pas changé.

    Dès que $1 a changé,
    1- on interrompt le traitement;
    2- on fait la division (sigma1/cpt) et (sigma2/cpt) et on recopie $1, $2, $3, $5 plus les deux valeurs qui viennent d'être calculées (sigma1 et sigma2) dans un fichier résultat...
    3- on réinitialise cpt, sigma1 et sigma2 et on reprend le traitement, jusqu'à la fin du fichier...

    Ma question: est-ce que c'est faisable facilement avec Python? En utilisant quelles structures de données (liste? tableau? tuple? dictionnaire? namedtuple?)

    Comme c'est ma première incursion réelle dans le monde de Python, évidemment je ne sais pas comment m'y prendre...

    Merci à celles/ceux qui ont davantage d'expérience et ont envie de la partager...

    Henri

  2. #2
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Le plus simple est sans doute un numpy array. Ca te permettrait de charger toutes les données d'un seul coup.

    Après, ce sont des traitements qui peuvent être automatisés par parcours du tableau et accumulation comme tu l'expliques.

  3. #3
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2008
    Messages : 327
    Points : 257
    Points
    257
    Par défaut
    Bonjour,

    Je n'ai pas tout compris sur ce que vous désirez faire, mais voici ce que j'aurai fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
     
    file = open("texte.txt", "r")
    resultat = open("resultat.txt", "w")
    ligne = file.split("\n")
    colonne = ligne[i].split("\t")
    entity = colonne[0]
    sigma1 = colonne[3]
    sigma2 = colonne[5]
    i = 1
    while i < len(ligne):
        colonne = ligne[i].split("\t")
        if colonne[0] == entity:
            sigma1 = sigma1 + colonne[3]
            sigma2 = sigma2 + colonne[5]
            i = i + 1
        else:
            resultat.write("%s\t%s\t%s\t%s\t%s\t%s\n" % (colonne[0], colonne[1], colonne[2], colonne[4], sigma1/i, simga2/i))
            i = 0
    resultat.close()
    file.close()
    Je ne les pas testé mais sa doit faire mot pour mot ce que j'ai compris ^^, sinon n'hesitez pas à me reformuler votre demande ...

    Bonne continuation

    Mickael

  4. #4
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    @ Apocalypses : open ne fait qu'ouvrir un fichier, il ne le lit pas

    De plus, si c'est un gros fichier, on peut très bien le lire ligne par ligne.

    Comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    # -*- coding: utf-8 -*-
     
    import sys
    import os
     
    def read_datas():
        try:
            with open("source.txt", "r") as source:
                with open("target.txt", "w") as target:
                    def get_values(l):
                        eof, count = False, 0.0
                        while 1:
                            count += 1.0
                            d = source.readline().split("\t")
                            if len(d) < 6:
                                eof = True
                                break
                            if d[0] != l[0]:
                                break
                            l[0:3], l[4] = d[0:3], d[4]
                            l[3] += eval(d[3])
                            l[5] += eval(d[5])
                        line = "\t".join([l[0], l[1], l[2], l[4], str(l[3]/count), str(l[5]/count)])
                        try:
                            target.write(line)
                            target.write("\n")
                        except:
                            print "Erreur d'écriture"
                        if eof:
                            print "Done"
                            sys.exit()
                        d[3] = eval(d[3])
                        d[5] = eval(d[5])
                        get_values(d)
     
                    l = source.readline().split("\t")
                    l[3] = eval(l[3])
                    l[5] = eval(l[5])
                    get_values(l)
        except IOError, why:
            print "Erreur de lecture", why
     
    if __name__ == "__main__":
        read_datas()
    La gestion d'erreur est minimaliste, à toi de voir les cas possibles.
    J'ai testé sommairement, ça fonctionne.

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 5
    Points : 2
    Points
    2
    Par défaut Merci aux personnes qui se sont manifestées
    Oui vraiment merci!
    Bon d'abord je ne sais pas comment dans la pratique répondre aux deux sympathiques personnes (Apocalypses et VinsS) qui se sont manifestées. J'ai cliqué sur "répondre à la discussion" et j'espère que c'est ce qu'il faut faire.

    Je n'ai pas pu exploiter les réponses encore, mais ça m'aide de voir comment vous vous y prennez. La proposition de Apocalypses est moins aboutie que celle de VinsS, mais il y a plein de choses intéressantes pour un débutant comme moi au niveau syntaxe Python.
    La proposition de VinsS m'a l'air excellente. Je l'ai faite tourner sur un de mes fichiers et il semble qu'on arrive au résultat (!!) à part seulement que dans le fichier de sortie ça se mélange un petit peu... la colonne $1 de mon fichier de départ ($1) n'est pas systématiquement affichée, et il n'y a pas de retour à la ligne après le traitement de chaque bloc de données (à $1 constant) . Pourtant le problème que j'ai soumis n'est pas si évident.
    BRAVO!!!
    Je dois m'occuper de ma petite fille, aussi excusez moi, je vous dis à demain!
    Merci infiniment!!
    Henri

  6. #6
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Ah oui, le saut de ligne, je l'ai rajouté dans le code.

    Pour les colonnes, je ne saisis pas bien, tu peux mettre un exemple, quelques lignes du source et quelques lignes du target qui montrent le problème ?

    Ca ne devrait pas être grand chose.

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 5
    Points : 2
    Points
    2
    Par défaut fichier source et fichier target (extraits)
    Bonjour VinsS et aussi Apocalypses!!

    Voila un extrait du fichier source et le fichier de sortie correspondant "traité à la main". Les en-tête sont là pour info évidemment...
    fichier source:
    ==========
    entity londd latdd age espece pourcent
    12 26.433333 53.416667 11693 564 4.59183673469388
    14 19.190833 46.477222 11547 564 6.03448275862069
    14 19.190833 46.477222 11827 564 3.2967032967033
    31 27.25 57.666667 11559 564 4.91071428571429
    31 27.25 57.666667 11713 564 6.50406504065041
    31 27.25 57.666667 11868 564 5.63002680965147
    31 27.25 57.666667 12177 564 2.03045685279188
    69 26.325833 59.133333 11735 564 2.11764705882353
    83 37.516667 66.375 11830 564 40
    117 7.1 43.8 11677 564 3.63636363636364
    202 28.183333 55.233333 11632 564 61.7733990147783
    202 28.183333 55.233333 11777 564 11.7259552042161
    203 ....
    ---------------------------------------rappel du traitement--------------------------------------------
    On parcourt le fichier source ligne par ligne et tant que $1 ne bouge pas on somme les contenus de $4 et $6 dans deux variables (sigma1 et sigma2) tout en incrémentant un compteur (cpt).

    Dès que l'on détecte que $1 a changé:
    - on calcule age_moy= sigma1/cpt et pourcent_moy = sigma2/cpt
    - on écrit $1, $2, $3, $5, age_moy et pourcent_moy dans le fichier résultat
    - on réinitialise cpt, sigma1 et sigma2
    - on reprend le traitement pour la nouvelle valeur de $1 qui a été détectée et
    ainsi de suite jusqu'à la fin du fichier:

    Comme résultat on veut toujours un fichier de six champs avec une seule ligne par entity cette fois avec pour age ($4) et pourcent ($6) leur valeur moyenne calculée,

    fichier target: traité "à la main"
    =========
    entity londd latdd age espece pourcent
    12 26.433333 53.416667 11693 564 4.59183673469388
    14 19.190833 46.477222 11687 564 4.665593027662
    31 27.25 57.666667 11829 564 4.76881574720201
    69 26.325833 59.133333 11735 564 2.11764705882353
    83 37.516667 66.375 11830 564 40
    117 7.1 43.8 11677 564 3.63636363636364
    202 28.183333 55.233333 11704 564 36.7496771094972
    ....

    On n'a donc plus qu'une seule ligne par entity avec en colonnes 4 et 6 les moyennes
    des valeurs "age" et "pourcent" correspondant à cette entité dans le fichier source.

    Les valeurs correspondant aux entity 12, 69, 83 et 117 du fichier source, qui n'ont qu'une seule entrée dans ce fichier, ont été recopiées telles qu'elles étaient dans le fichier source. Ici seules trois entités ont été traitées: 14 (cpt = 2), 31 (cpt =4) et 202 (cpt = 2).

    Si tu peux arranger ton code VinsS merci beaucoup car je ne l'ai pas encore tout décrypté. J'ai beaucoup à apprendre sur Python!

    Obiwan

  8. #8
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Salut, j'ai testé avec ton fichier, j'obtiens ceci :

    source.txt
    12 26.433333 53.416667 11693 564 4.59183673469388
    14 19.190833 6.477222 11547 564 6.03448275862069
    14 19.190833 46.477222 11827 64 3.2967032967033
    31 27.25 57.666667 11559 564 4.91071428571429
    31 27.25 57.666667 11713 564 6.50406504065041
    31 27.25 57.666667 11868 564 5.63002680965147
    31 27.25 57.666667 12177 564 2.03045685279188
    69 26.325833 9.133333 11735 564 2.11764705882353
    83 37.516667 66.375 11830 564 40
    117 7.1 43.8 11677 564 3.63636363636364
    202 28.183333 55.233333 11632 564 61.7733990147783
    202 28.183333 55.233333 11777 564 11.7259552042161
    target.txt
    12 26.433333 53.416667 564 11693.0 4.59183673469
    14 19.190833 46.477222 64 11687.0 4.66559302766
    31 27.25 57.666667 564 11829.25 4.7688157472
    69 26.325833 9.133333 564 11735.0 2.11764705882
    83 37.516667 66.375 564 11830.0 40.0
    117 7.1 43.8 564 11677.0 3.63636363636
    202 28.183333 55.233333 564 11704.5 36.7496771095
    Ce n'est pas le résultat attendu ?
    Par contre, l'idée de séparer les datas par des tabulations c'est pas très pratique, mon éditeur les remplace par des espaces, il eut été préférable de choisir la virgule comme séparateur.

  9. #9
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 5
    Points : 2
    Points
    2
    Par défaut vraiment au poil!!
    Bonjour,
    Oui ça tourne parfaitement. Le résultat correspond bien à ce que j'attendais, c'est nickel.

    Par contre j'ai quelques difficultés pour comprendre la structure du code, car je ne suis pas très au fait du système des indentations qui semble en fait tout structurer.

    J'ai eu un peu de mal à voir où se terminait la fonction "get_value()", avant de comprendre qu'elle s'appelait elle-même.

    Pour "read_data()" je ne comprends pas pourquoi le second "with open" est décalé d'une indentation par rapport au premier.

    Bref ton code est super propre et bien écrit, et très instructif.

    Je te remercie vraiment, je vais pouvoir m'en inspirer à l'avenir.

    Une dernière question: je travaille sous Linux (Ubuntu 10, 11 ou Fedora 14), et cherche encore un environnement de développement Python. Lequel conseillerais-tu? en ce moment j'essaie SPE.

    Merci encore et à un de ces jours Vincent,

    Henri

  10. #10
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Oui en Python les indentations ne sont pas conventionnelles mais obligatoires, et pas de mélange espaces/tabulations ça ne passe pas.

    with open() à la particularité qu'il fermera toujours le fichier ouvert lorsque l'on quitte son champ d'action, pour cela cette instruction ouvre un bloc de code, ce qui signifie que dans cet exemple, le deuxième fichier sera fermé en premier.

    Pour ma littérature, j'utilise Gedit, eh oui, sinon pour des trucs plus importants, j'utilise Eric,
    il est dans les dépôts Ubuntu, mais, je previens, c'est un gros machin, faut apprendre à s'en servir.

  11. #11
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonsoir,

    Juste une précision sur ceci:
    Citation Envoyé par VinsS Voir le message
    Pour ma littérature, j'utilise Gedit, eh oui, sinon pour des trucs plus importants, j'utilise Eric,
    il est dans les dépôts Ubuntu, mais, je previens, c'est un gros machin, faut apprendre à s'en servir.
    A signaler geany, sur le dépôt universe. Plus accessible peut être pour commencer.
    Mais c'est vrais que j'utilise geany et gedit en même temps...

    Bon code

    Ps: A noter qu'un with open() n'est pas compatible à 100% Mais bon, je travaille sur des distribs serveur quelques peut... A la bourre de ce coter là
    Merci d'utiliser le forum pour les questions techniques.

Discussions similaires

  1. Extraction des données d'un fichier text en vb net
    Par sihammaster dans le forum VB.NET
    Réponses: 5
    Dernier message: 29/11/2009, 15h37
  2. Extraction de données d'un fichier texte
    Par boobz dans le forum Langage
    Réponses: 1
    Dernier message: 30/03/2008, 11h40
  3. Réponses: 4
    Dernier message: 05/02/2008, 11h08
  4. Extraction de données dans un fichier texte en VB6 !
    Par rockroa dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 21/06/2006, 16h00
  5. Perl: Extraction de données d'un fichier texte ?
    Par fifto dans le forum Langage
    Réponses: 1
    Dernier message: 27/03/2006, 16h01

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