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 :

Manipulation de fichiers texte


Sujet :

Python

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 13
    Par défaut Manipulation de fichiers texte
    Bonsoir à tous,

    Avant tout, je précise que je suis débutante sur Python, et en programmation en général... Mes connaissances sont loin d'être optimales !

    Bref, je résume ce qui me pose problème ce soir. Je fais des études de linguistique et j'aimerais utiliser Python pour faire certains calculs sur des textes (par exemple la fréquence de certains mots, des moyennes sur le nombre de mots par phrase, etc...).

    Je sais comment ouvrir un fichier texte dans Python, mais j'ai des soucis en ce qui concerne l'application d'une fonction ou d'un script au contenu de ce fichier.
    Je ne sais pas s'il existe une possibilité de faire cela directement, je vous montre comment j'ai procédé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    import codecs
    f=codecs.open('texte2.txt',encoding='iso-8859-1')
    data=f.read()
    J'ai donc essayé comme précédent en transformant le contenu de mon fichier en une chaine pour pouvoir agir dessus.
    Mais j'ai l'impression que cette chaine est bien trop grosse pour pouvoir être manipulée et à chaque fois que je tente une opération dessus le mode interactif de Python plante totalement et ne répond plus... (-> par exemple un data.split() ou pour couper le texte en utilisant des motifs)

    Pour avoir une idée de la longueur du genre de texte que j'utilise :
    http://www.gutenberg.org/files/11494/11494-8.txt

    Voilà donc je ne sais pas trop s'il y a un moyen de faire cela plus simplement sans passer par une chaine ?

    En tout cas désolée d'avance si ma question vous parait simpliste mais j'avoue que j'ai cherché dans différents cours et que dès qu'il s'agit de manipulation de fichiers les tutos parlent de suite choses très complexes et non pas de simple textes... Donc il n'est pas évident de trouver une réponse

    Merci d'avance pour votre aide,


    Sycosis

  2. #2
    Membre émérite

    Profil pro
    Inscrit en
    Août 2004
    Messages
    723
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 723
    Par défaut
    Je pense que pour ce genre de fichier il serait intéressant de lire ligne par ligne, il est en effet assez volumineux.

    Au cas où:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    import codecs
    f=codecs.open('texte2.txt',encoding='iso-8859-1')
    for ligne in f:
        #faire quelque chose avec la ligne

  3. #3
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Le fichier n'est pas si énorme que ça; même en le lisant en un bloc ça ne devrait pas être aussi lent. words = data.split() sur les données du fichier est presque instantané chez moi. Mais peut être demandes-tu d'afficher le résultat, ce qui très lent car les fonctions d'affichage sont lentes (et de toute façon, à quoi sert d'afficher une liste de 48276 chaînes ?).

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 13
    Par défaut
    Merci pour vos réponses.

    Actuellement je cherche à segmenter le texte en mots et en phrases...
    J'aurais besoin d'afficher les résultats, oui.

    Je voudrais utiliser un script de ce genre, pour les phrases par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    	import re
    	delim=r'!|\?|\.'
    	p=re.compile(delim)
            mots=p.split(chaine)
    Le souci c'est que je sais le faire sur une chaine, basique mais pour faire en sorte de le faire sur tout mon fichier en créant une boucle pour qu'il soit parcouru ligne par ligne si cela est nécessaire, je sèche...

  5. #5
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Citation Envoyé par Sycosis Voir le message
    J'aurais besoin d'afficher les résultats, oui.
    A cette étape ? Je ne vois pas l'intérêt. Si c'est pour vérifier que la découpe se passe comme prévu, tu peux en afficher juste une partie. Ou alors mettre au point le programme en utilisant un fichier de petite taille et le remplacer par le fichier complet une fois qu'il est terminé.

    Le code avec l'expression régulière ci-dessus tourne très bien avec la chaîne "basique" data de ton premier post. Le faire ligne par ligne, dans ce cas-ci, va compliquer les choses vu qu'une phrase peut être contenue sur plusieurs lignes.

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 13
    Par défaut
    Ou alors mettre au point le programme en utilisant un fichier de petite taille et le remplacer par le fichier complet une fois qu'il est terminé.
    Je pense que je vais faire cela et que ça sera plus pratique :p

    Maintenant, j'ai un autre challenge qui m'attend : J'aimerais calculer la fréquence des mots dans le texte pour obtenir une liste des mots qui reviennent plusieurs fois dans le texte (par exemple 5, 10 ou 15 fois, je pense que j'ajusterai le seuil ensuite pour pouvoir avoir le nombre de mots qui me convient).

    Et là... j'avoue que je ne sais vraiment pas par où m'y prendre pour commencer.
    J'ai déjà utilisé des fonctions comme count dans des exercices mais on compte toujours quelque chose en particulier : exemple le nombre de "a".
    Mais là pour compter les mots qui reviennent !

  7. #7
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Pour compter le nombre d'occurrences de chaque mot, il faut une structure de données qui te permet d'associer un nombre (le compteur) à un mot donné. La structure qui s'impose dans ce cas-là en Python est le dictionnaire, avec comme clés les mots et comme valeurs les compteurs. Tu parcours ta liste de mots; pour chaque mot, s'il n'est pas encore dans le dictionnaire tu l'ajoutes en initialisant le compteur à 1; s'il y est déjà tu incrémentes le compteur (une implémentation alternative est d'utiliser la classe defaultdict dans le module collections).

    Tu pourrais être intéressée par cette discussion, qui concernait aussi la linguistique: http://www.developpez.net/forums/d65...-fichier-long/. Cela peut te paraître un peu compliqué pour l'instant, mais il y a un tas de manipulations intéressantes de listes et de dictionnaires pour résoudre le genre de problèmes auxquels tu seras confrontée dans cette discussion.

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 13
    Par défaut
    Pour compter le nombre d'occurrences de chaque mot, il faut une structure de données qui te permet d'associer un nombre (le compteur) à un mot donné. La structure qui s'impose dans ce cas-là en Python est le dictionnaire, avec comme clés les mots et comme valeurs les compteurs. Tu parcours ta liste de mots; pour chaque mot, s'il n'est pas encore dans le dictionnaire tu l'ajoutes en initialisant le compteur à 1; s'il y est déjà tu incrémentes le compteur (une implémentation alternative est d'utiliser la classe defaultdict dans le module collections).
    Ca serait quelque chose dans ce genre là ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    d = {}      
    for l in m:
        if l in d: 
            d[l] = d[l]+1  
        else: 
            d[l] = 1 
     
    print d 
     
    for clef in d: 
        if (d[clef] > 1): 
            print clef +" "+ str(d[clef])
    J'ai déjà fait ça mais encore une fois c'est dans le cadre de la recherche des occurrences d'une lettre dans un mot, j'ai un peu de mal à l'adapter à l'échelle supérieure pour chercher des mots dans un texte ! :p

    Concernant le topic que tu me linkes, effectivement je l'ai parcouru tout à l'heure et ça reste vraiment compliqué avec beaucoup de fonctions que nous n'avons pas encore étudiées.

  9. #9
    Membre émérite
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Par défaut
    Salut, c'est bien le concept oui

    pour obtenir les mots, c'est en fait très simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    >>> 'Ah, quelle belle phrase, non ?'.split()
    ['Ah,', 'quelle', 'belle', 'phrase,', 'non', '?']
    mais bon, il vaudrait peut-être mieux définir une fonction qui nous donnerait un meilleur résultat, quelquechose dans ce goût là :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    >>>def getWords(txt):
        words=[]
        for raw_w in txt.split():
            if not raw_w.isalpha():
                word=''
                for char in raw_w:
                    if char.isalpha():word+=char
            else: word=raw_w
            if word!='':words.append(word)
        return words
     
    >>> getWords('Ah, quelle belle phrase, non ?')
    ['Ah', 'quelle', 'belle', 'phrase', 'non']
    Après, y'a moyen de simplifier, mais comme tu débute, mieux vaudra y revenir un peu plus tard :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    >>> def getWords2(txt):
        words=[''.join([y for y in x if y.isalpha()]) for x in txt.split()]
        while '' in words: words.remove('')
        return words
     
    >>> getWords2('Ah, quelle belle phrase, non ?')
    ['Ah', 'quelle', 'belle', 'phrase', 'non']

  10. #10
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 13
    Par défaut
    Donc si j'ai bien compris il faudrait que je transforme d'abord le texte en liste (découpé en mots) et qu'ensuite j'utilise le script avec le dictionnaire ?

    Je me demande si la fonction que tu me donnes pour segmenter en mots va fonctionner sur un texte aussi long... Sinon je suppose que l'on peut enlever "Return words" pour éviter d'afficher les résultats ? (puisque c'est ce qui plante :p)

  11. #11
    Membre émérite
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Par défaut
    Sinon je suppose que l'on peut enlever "Return words" pour éviter d'afficher les résultats ? (puisque c'est ce qui plante :p)
    Non non non, en fait c'est juste le comportement de la console interactive qui fait que le résultat nous est afficher... return c'est ce qui nous permet d'obtenir lla valeur de words, si il n'y était pas, la fonction ferait ce qu'on lui demande sans 'retouner' de résultat, ce serait comme si tu tapais sur ta calculette 3+2, que la puce fasse le calcul, mais garde le résultat pour elle, aucune utilité, il faut qu'elle le retourne. Or dans la console interactive, si l'appel à une fonction est faite 'nue' -non attribuée à une variable par ex- la console se dit qu'il faut alors retourné la valeur retournée par la fonction à l'utilisateur, mais in-script, rien ne serait retourné... heu... c'est clair ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    text=getWords2('Ah, quelle belle phrase, non ?')
    # et text aura pour valeur : ['Ah', 'quelle', 'belle', 'phrase', 'non']
    Ensuite il faudra peut-être modifier la fonction pour qu'elle prenne en compte également les chiffres, auquel cas il ne faut pas utiliser ''.isalpha(), mais ''.isalnum()

    Enfin, non il ne faut pas forcément appliquer directement la fonction à tout le document en une fois... comme sugeré plus haut, tu peut lire le fichier ligne par ligne, ce qui prend moins de place en memoire, et je suppose demande moins d'effort au CPU :
    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
    def getWords(txt):
        '''Fonction servant à obtenir une liste des mots contenu dans le texte passe en parametre'''
        words=[]
        for raw_w in txt.split():
            if not raw_w.isalpha():
                word=''
                for char in raw_w:
                    if char.isalpha():word+=char
            else: word=raw_w
            if word!='':words.append(word)
        return words
    def wordsCounting(lst,dico):
        """lst : liste de mots
    dico : dictionnaire ou stocker les resultats
    Routine servant a compter les mots d'une liste de mots"""
        for word in lst:
            if dico.has_key(word):
                dico[word]+=1
            else: dico[word]=1
    DICO={}
    for line in file('Le/Chemin/De/Ton/Fichier_Texte'):
        wordsCounting(getWords(line),DICO)
     
    #Ensuite on peut par exemple ecrire les resultats dans un fichier:
    f_out=open('D:/res.txt','w') #'w' pour write, 'r' pour read, et 'a' pour append, ici c'est écrire qui nous intéresse
    for word in sorted(DICO.keys()):
        f_out.write('%s\t: %i'%(word,DICO[word]))
    f_out.close()
    La différence entre une routine et une fonction provient précisément de la présence ou non de "return" : une fonction avec return, est véritablement une fonction, c'est à dire qu'on peut faire la chose suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def toto(a,b):
            res=a+b
            return res
    c=toto(1,2) #c sera = a 3
    alors que sans return la "fonction" devient une routine:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    toto(a,b):
            global res #sert à dire que res sera accessible en dehors de toto()
            res=a+b
    c=toto(1,2) #c sera = a None
    #mais res sera = 3
    [code]

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 13
    Par défaut
    Rebonjour !
    Merci pour tes explications

    Après un peu de galère j'ai réussi a faire fonctionner (\o/) le code que tu m'as donné en procédant comme suit :

    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
     
     
    def getWords(txt):
        words=[]
        for raw_w in txt.split():
            if not raw_w.isalpha():
                word=''
                for char in raw_w:
                    if char.isalpha():word+=char
            else: word=raw_w
            if word!='':words.append(word)
        return words
     
    def wordsCounting(lst,dico):
        """lst : liste de mots
    dico : dictionnaire ou stocker les resultats
    Routine servant a compter les mots d'une liste de mots"""
        for word in lst:
            if dico.has_key(word):
                dico[word]+=1
            else: dico[word]=1
    DICO={}
    for line in file('texte2.txt'):
        wordsCounting(getWords(line),DICO)
     
    f=open('texte2.txt','r')
    data=f.read()
     
    getWords(data)
    lst=getWords(data)
    dico={}
    wordsCounting(lst,dico)
     
    f_out=open('D:/res2.txt','w') #'w' pour write, 'r' pour read, et 'a' pour append, ici c'est écrire qui nous intéresse
    for word in sorted(DICO.keys()):
        f_out.write('%s\t: %i'%(word,DICO[word]))
    f_out.close()
    Je ne sais pas si j'ai bien fait les choses mais ça a marché donc je présume que ce n'est pas si mal.
    La liste obtenue a l'air très correcte même si elle comporte quelques erreurs de découpage avec certains mots composés et qu'elle ne prend pas en compte les apostrophes, je suis déjà heureuse d'avoir eu un résultat ! :p

    Comment puis-je faire pour afficher les résultats directement ?
    Et, je ne sais pas s'il y a un moyen d'organiser les résultats pour les afficher par ordre décroissant ?

  13. #13
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Dans un script, des expressions comme ne servent à rien; ce n'est que dans l'interpréteur interactif qu'il affiche le résultat d'une expression, pas dans un script. Si tu veux afficher quelque chose depuis le script, utilise print: Ensuite, ton script recalcule plusieurs fois la même chose! Au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    print getwords(data)
    lst = getwords(data)
    Il vaut mieux écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    lst = getwords(data)
    print lst
    Mais il y a d'autres répétitions dans ton script (getwords est appelé 3 fois sur les mêmes données).
    Voilà une version améliorée; à la fin je trie par ordre décroissant du nombre d'occurrences, comme tu l'as demandé:
    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
    def getWords(txt):
        words=[]
        for raw_w in txt.split():
            # filter ne va garder que les caractères de raw_w
            # (2eme argument) qui passent le test str.isalpha (1er arg)
            # le résultat est donc identique à ton code
            word = filter(str.isalpha, raw_w)
            if word!='': words.append(word)
        return words
     
    def wordsCounting(lst):
        """lst : liste de mots
    Routine servant a compter les mots d'une liste de mots
    Retourne un dictionnaire contenant les resultats"""
        dico = {}
        for word in lst:
            if word in dico:    # identique à dico.has_key(word) mais
                dico[word]+=1   # ce dernier est déprécié
            else: dico[word]=1
        return dico
     
    f = open('texte2.txt','r')
    data = f.read()
    f.close()
    lst = getWords(data)
    #print lst
    dico = wordsCounting(lst,dico)
    #print dico
     
    f_out = open('D:/res2.txt','w')
    # La ligne de code suivante convertit le dictionnaire en une liste de couples,
    # pour pouvoir les trier ensuite. Le nombre d'occurrences est mis en premier
    # dans le couple pour faciliter le tri sur celui-ci.
    lst = [(count, word) for word, count in dico.iteritems()]
    lst.sort(reverse=True)
    for count, word in lst:
        f_out.write('%-15s: %i'% (word,count))
    f_out.close()
    Je n'ai pas exécuté ce code; il se peut qu'il y ait l'une ou l'autre petite erreur.

Discussions similaires

  1. Manipulation de fichiers textes
    Par chlours dans le forum C++
    Réponses: 3
    Dernier message: 22/01/2008, 13h33
  2. Réponses: 2
    Dernier message: 07/10/2007, 19h52
  3. [Débutant] Manipulation de fichier texte ?
    Par Badaboumpanpan dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 26/06/2007, 10h42
  4. Manipulation de fichiers textes - fonction
    Par kromartien dans le forum C
    Réponses: 2
    Dernier message: 11/06/2007, 00h02
  5. manipuler un fichier texte
    Par bassidi meryeme dans le forum Langage
    Réponses: 2
    Dernier message: 29/10/2005, 00h23

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