Aide traitement données fichier texte (détection mot, séparation données...)

AlexM31 Messages postés 10 Statut Membre -  
 vortex -
Bonjour,

Je vous écris car j'aurais besoin d'aide sur ma mission. J'ouvre un fichier txt et je dois afficher certaines données. J'en ai 4 particulière
J'arrive l'ouvrir et l'afficher en entier.

Mon objectif :
1) pouvoir afficher les données après le mot "Mesures" j'utiliser un for, ca marche au premier test mais lors des autres "Mesures" dans mon fichier txt, ils sont affichés sur l'invite python

2) Mes données sont classées en :

"
Frequence Max
Frequence Min
Sweeptime

Mesures :

Data Fréquence
Date dB
Data Fréquence
Data dB
.
.
."

L'objectif serait d'avoir à l'aide du 1) de les dispatcher avec un mot me permettant d'afficher la data juste après ("fréquence Max :" 25000) ou juste en dessous
("Mesures"
12.045
25000
)

Par la suite je dois les incorporer dans une IHM en PyQt mais cette étape je sais comment la réaliser.
J'ai besoin de conseils sur le traitement des données de ficher, pouvoir dispatcher les données, les traiter comme je désire etc...

Voici mon code :

self.name, _filtre = QtWidgets.QFileDialog.getOpenFileName(self.centralwidget)

chaine = "Mesures"

with open(self.name, "r") \
as t:
for lines in t:
if chaine in lines:
# m = chaine + 1

content = t.read()
# data = t.readlines()[chaine. + 1]
print(content)


Une image du type de ficher txt :


Je vous remercie pour votre temps et votre aide, je reste à disposition pour d'autres infos si je n'ai pas bien expliquer mon problème

Alexis

10 réponses

  1. Phil_1857 Messages postés 1883 Date d'inscription   Statut Membre Dernière intervention   169
     
    Bonjour,

    L'indentation étant importante en Python, merci de copier/coller ici ton code complet avec les balises de code
    mode d'emploi:
    https://codes-sources.commentcamarche.net/faq/11288-les-balises-de-code

    Visuellement, ça doit ressembler à ceci (avec la coloration syntaxique) :

    def test():
        print('test')
    
    test()
    


    C'est marrant, ça ressemble à une question posée sur un autre forum ...... :-)
    0
    1. AlexM31 Messages postés 10 Statut Membre
       
      Bonjour Phil, j'ai posé une question différente sur un autre forum ;) ayant réussi à me faire avancer, j'ai poursuivi mon projet avec l'aide précieuse mais je fais face à un autre souci que je n'arrive pas à résoudre et je ne souhaite pas déranger les mêmes personnes m'ayant aider tout simplement

      Pour l'indentation j'ai pourtant suivi la même procédure que partagé dans le lien
      0
  2. vortex
     
    Bonsoir,

    Je ne comprends pas, AlexM31, où se situe ton problème.

    Tu dis n'avoir aucun problème à incorporer ton bazar à ton ihm, mais tu dis dans ton 1) que tu as un problème d'affichage, en utilisant un simple print, c'est paradoxal ce que tu dis.

    On ne sait pas vraiment comment est structuré ton fichier, a-t-il un format standard connu ? Ou c'est un truc non standard ? Si format à l'emporte pièces, il faudra peut-être utiliser une ou plusieurs expressions régulières pour récupérer ce dont tu as besoin pour bosser.

    Bref, difficile de déterminer ce qui te pose souci.
    0
    1. AlexM31 Messages postés 10 Statut Membre
       
      Bonjour vortex, l'affichage du contenu entier fonctionner.

      J'ai expliqué le format de mon fichier m'ai je vais essayer de le développer un peu plus.
      C'est une base de données automatisées, ce qui m'intéresse sont les données numériques qui sont regroupées de la sorte.
      J'ai 461 prises de mesures avec : - Amplitude en DB d'un analyseur de spectre
      - Fréquence de l'amplitude

      Ce qui donne comme sur l'image de mon post dans mon fichier txt

      """MESURES : (un string que je rajoute dans mon code f.write('\n' + "Mesures" + '\n'))

      fréquence amplitude(point1)
      Valeur amplitude en dB (point 1)
      fréquence amplitude(point2)
      Valeur amplitude en dB (point 2)
      .
      .
      fréquence amplitude(point461)
      Valeur amplitude en dB (point 461)"""


      Dans le code donné du sujet, je cherche à traiter ces données et en tirer que les valeurs numériques, je dois donc extraire du read le "MESURES :"


      Mon problème est que j'ai un nombre illimité de test qui peuvent s'ajouter. Si j'ai 50 tests j'aurais 50 fois

      """MESURES : (un string que je rajoute dans mon code f.write('\n' + "Mesures" + '\n'))

      fréquence amplitude(point1)
      Valeur amplitude en dB (point 1)
      fréquence amplitude(point2)
      Valeur amplitude en dB (point 2)
      .
      .
      fréquence amplitude(point461)
      Valeur amplitude en dB (point 461)"""



      Je cherche à supprimer à chaque fois le "Mesures :"
      Et par la suite je vais chercher à trier les valeurs = recupérer, traiter et afficher les fréquences sur un tableau de mon IHM et pareillement pour les valeurs d'amplitude


      De plus le format, si j'ai bien compris le sens, je n'en ai pas de connu, j'ai crée la disposition du contenu moi même dans le fichier .txt

      Pour finir, en gros ce que je souhaite c'est, lire dans mon fichier que les fréquences et amplitude, les afficher ensuite

      PS: Désolé pour ce retour tardif avec les vacances, si d'autres informations sont nécessaires j'essayerai d'y repondre du mieux que je peux avec les connaissances que j'ai
      0
      1. AlexM31 Messages postés 10 Statut Membre > AlexM31 Messages postés 10 Statut Membre
         
        0
      2. vortex > AlexM31 Messages postés 10 Statut Membre
         
        Bonjour,

        Approche simpliste (à tester).

        measures = []
        
        with open('le_fichier_a_lire') as f:
            i = 0
            read = False
            for line in f:
                if 'Mesures' in line:
                    read = True
                    continue
                if not read:
                    continue
                data = line.strip()
                if not data:
                    continue
                if not i % 4:
                    measures.append([])
                try:
                    measures[-1].append(float(data))
                except ValueError:
                    if not measures[-1]:
                        measures.pop()
                    break
                i += 1
        
        print(measures)


        Mais pourquoi ne pas enregistrer tes mesures dans un fichier csv (ou autre avec sqlite par exemple) réservé uniquement à l'enregistrement de tes valeurs ?
        0
      3. AlexM31 Messages postés 10 Statut Membre > vortex
         
        Bonjour,
        merci beaucoup pour ce superbe code, il fonctionne super bien, j'ai modifié le i % 4 en i % 922 pour avoir en une seule chaine toutes les valeurs

        J'ai 2 questions
        - Penses tu que créer 2 chaines au lieu d'une et de rajouter un for peut fonctionner ? Pour classer les fréquence et amplitudes ?

        - Pourquoi ca ne m'affiche que mon premier test et non les suivant ? sachant que j'ai plusieurs fois Measures et ton code me permet de me balader dans tout mon fichier

        Pour le fichier CSV, j'y avais pensé mais étant juste une "sauvegarde" des données de l'analyseur, mon entreprise ne souhaite pas utilisé de base de données à proprement dite

        Encore merci pour ce code
        0
  3. Utilisateur anonyme
     
    Bonjour

    Tu connais les expressions régulières (regex ?) ça pourrait répondre à ton besoin.
    0
    1. AlexM31 Messages postés 10 Statut Membre
       
      Bonjour,

      Je connaissais pas mais je viens d'aller feuilleter. Ca me serait utile pour la recherche du mot "mesures" avec
      re.search("Mesures") 
      ?
      (ou re.match)
      0
  4. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  5. vortex
     
    Bof, j'aime bien les regex, mais ça n'aide pas à se creuser un peu les méninges pour faire ça dans une boucle et comment gérer la lecture des lignes du fichier en fonction de où on en est.

    Mais soit.

    import re
    
    mesures = []
    keys = ('frequences', 'amplitudes')
    with open('KHynoznLzfC_test-test-test.txt') as f:
        content = f.read()
    
    for m in re.finditer('Mesures\n+((?:-?\d+\.\d+\n)+)', content):
        mesures.append({k:[] for k in keys})
        for i, v in enumerate(m[1].splitlines()):
            mesures[-1][keys[i % 2]].append(float(v.strip()))
    
    # Vérifications quelconques
    print(mesures[0]['frequences'][0:5])
    print(mesures[0]['amplitudes'][0:5])
    0
  6. Utilisateur anonyme
     
    Je pensais plutôt traiter le fichier d'un coup avec une substitution la regex serait
    [^M]*M?esures\n\n(-?\d+\.\d+)\n(-?\d+\.\d+)\n(-?\d+\.\d+)[^M]*

    avec l'option multiline désactivée et la substitution pourrait être
    Mesures;Type 1 = \1; Type 2 = \2; Type 3 = \3\n


    L'idée est de faire matcher tout le texte avec les 3 valeurs qu'on veut extraire dans un groupe.
    Et à la place écrire le texte qu'on veut avec le contenu des groupes.
    Voici l'exemple https://regex101.com/r/DCyLq7/3

    Je ne code pas en python, sauf de temps à autre pour le forum sur un éditeur en ligne.
    J'essayerai de mettre ça en musique si AlexM31 pense que ça correspond à ce qu'il recherche
    0
  7. Utilisateur anonyme
     
    J'ai essayé ça
    import re
    #texte contient tout le texte du fichier
    patern = r"[^M]*M?esures\n\n(-?\d+\.\d+)\n(-?\d+\.\d+)\n(-?\d+\.\d+)[^M]*"
    substitution = "Mesures;Type 1 = \g<1>; Type 2 = \g<2>; Type 3 = \g<3>\n"
    print(re.sub(patern,substitution,texte, flags = re.M))


    sur un éditeur en ligne (pour lui les groupes doivent s'appeler \g<1> \g<2> etc...) et ça marche

    La variable texte contient tout le texte du fichier exemple sur cjoint

    Je l'ai rempli de cette façon
    texte = """2021-08-03 11:29:55.176783
    0.0
    
    20000.0
    20000.0
    3.0
    3.0
    20000000000000.0
    +20
    
    0.0
    
    Mesures
    ....
    """

    0
  8. AlexM31 Messages postés 10 Statut Membre
     
    Salut Whismeril et vortex.

    Merci pour l'explication sur les regex, c'est très utile. J'ai testé ton code, qui fonctionne très bien. Le soucis, serait que mes 2 données principale : les 461 frequences et 461 amplitude soit dans une liste.
    Ca me permettrait de remplir facilement un QTableWidget à base d'un for de range 461.
    Les 3 groupes sont traités en même temps dans une seule variable, ce qui peut être contraignant sur comment derrière les dispatcher
    (Si je me trompe, à me corriger)

    Le code de Vortex :

    import re
    
    mesures = []
    keys = ('frequences', 'amplitudes')
    with open('test_test_test.txt') as f:
        content = f.read()
    
    for m in re.finditer('Mesures\n+((?:-?\d+\.\d+\n)+)', content):
        mesures.append({k:[] for k in keys})
        for i, v in enumerate(m[1].splitlines()):
            mesures[-1][keys[i % 2]].append(float(v.strip()))
    
    # Vérifications quelconques
    freq = mesures[0]['frequences'][0:461]#indice premiere liste mesure
    print(freq)
    print(mesures[1]['amplitudes'][0:922])


    me classe par liste.
    J'aimerais savoir si
    mesures = []
    je pourrais créer 2 listes ? qui aurait chacune leur data.

    J'avais en tête de passer également par un for pour cette partie
    freq = mesures[0]['frequences'][0:461]#indice premiere liste mesure
    print(freq)
    print(mesures[1]['amplitudes'][0:922])


    Me permettrait de renseigner dans mesures[XXX] et dans frequence [XXX], amplitude [XXX] aucune precision de longueur
    Je sais combien j'ai de tests ici, 3, donc je peux varier la range
    frequence [0:461], frequence [0:922], frequence [0:1383]
    amplitude[0:461], amplitude [0:922] , amplitude [0:1383]

    Si j'ai 40 tests, pour "automatiser" mettre par exemple

    for fichier_total in XXX:
    frequence[fichiertotal]

    Serait ce une bonne idée ? et est ce possible surtout ?
    0
    1. Utilisateur anonyme
       
      Comme je te l'ai dit je ne code pas en python.
      Les regex sont un outil puissant de traitement du texte (mais pas la seule façon de faire)
      Votex t'a montré une façon de se servir des regex pour extraire tes données et moi une autre façon pour récupérer un texte "complet".
      Mais les façons de s'en servir sont "infinies" , pour la suite, je te laisse avec vortex et phil
      0
    2. vortex
       
      Bonjour,

      mesures est une liste de dictionnaires contenant deux listes, chaque liste contient 461 valeurs.

      Et question parcours des valeurs, je ne vois pas où est le problème.

      # Lecture de toutes les fréquences
      for dic in mesures:
          for v in dic['frequences']:
              print(v)


      # Lecture du deuxième groupe de fréquences
      for v in mesures[1]['frequences']:
          print(v)


      Et tu peux savoir combien il y a de groupes avec un simple len de mesures, mais si la structure que j'ai choisi, ne te convient pas et que tu préfères tout stocker dans 2 simples listes, alors, il n'y a pas grand chose à modifier.

      import re
      
      keys = ('frequences', 'amplitudes')
      mesures = {k:[] for k in keys}
      with open('KHynoznLzfC_test-test-test.txt') as f:
          content = f.read()
      
      for m in re.finditer('Mesures\n+((?:-?\d+\.\d+\n)+)', content):
          for i, v in enumerate(m[1].splitlines()):
              mesures[keys[i % 2]].append(float(v.strip()))
      
      
      print(mesures['amplitudes'][-1:-6:-1])
      print(len(mesures['frequences']) // 461 )
      print(mesures['frequences'][461 * 2:461 * 2 + 10])


      Le but est quand même que tu comprennes ce code et que l'adaptes à ta sauce, et si tu ne comprends pas certaines choses dans ce code, dis-le, on pourra te l'expliquer =)
      0
  9. AlexM31 Messages postés 10 Statut Membre
     
    Bonjour, après une analyse du code, j'ai compris le fonctionnement.
    Le premier for
    for m in re.finditer('Mesures\n+((?:-?\d+\.\d+\n)+)', content):
        mesures.append({k:[] for k in keys})
        for i, v in enumerate(m[1].splitlines()):  #i = nombres de lignes apres"Mesures", v = valeur de la ligne i
            mesures[-1][keys[i % 2]].append(float(v.strip()))
    

    Me permet de détecter après "Mesures" les données et leurs lignes

    Pour le code des fréquences
    for dic in mesures:
        for v in dic['frequences']:
            print(v)

    Cela me sort en sorti les valeurs "d'amplitude" également



    J'ai l'idée de rajouter un code liant 461 mesures à la suite par 2 fois et recommencer.
    Pourriez-vous m'expliquer comment créer une liste qui s'incrémente de 461 valeurs et qui s'efface qvp
    J'ai pensé à la remplir par un append(valeur) et la stopper à 461

    tri =[]
            #print tri[freq]
    for dic in mesures:
         for amp in dic['amplitudes']:
             print(amp)
             for m in range(461):
                  #affiche toutes les amplitudes
             #print(type(amp))
                 tri[m].append(float(amp))
    0
    1. vortex
       
      Bonsoir,

      Désolé, mais je ne comprends pas grand chose à ce que tu veux faire.

      Comme je t'ai déjà indiqué, la liste mesures contient des dictionnaires ayant 2 items avec pour clefs amplitudes et fréquences et pour valeurs une liste d'exactement 461 valeurs chacunes.

      Quel est le problème en fait ? Pourquoi vouloir stocker ça dans une autre liste ? En quoi la liste dic['amplitudes'] te pose problème ?

      J'ai l'impression que tu n'arrives pas à comprendre cette simple structure.
      0
  10. AlexM31 Messages postés 10 Statut Membre
     
    Bonjour vortex,

    il n'est pas question de compréhension. Ici dic['amplitudes'] me retourne les valeurs des amplitudes ET des fréquences.

    J'ai fait 2 for avec dic['amplitudes'] et ['frequences'] puis j'en ai enlevé un pour visualiser 1 seule donnée. Et j'ai eu les 2 types de mesures.
    0
    1. vortex
       
      Bonjour,

      Si tu testes avec le fichier que tu as fourni, les items amplitudes ne contiennent pas les valeurs des fréquences, je ne vois pas comment ce serait possible puisque toutes les listes ont 461 valeurs.

      import re
      
      mesures = []
      keys = ('frequences', 'amplitudes')
      with open('le_fichier') as f:
          content = f.read()
      
      for m in re.finditer('Mesures\n+((?:-?\d+\.\d+\n)+)', content):
          mesures.append({k:[] for k in keys})
          for i, v in enumerate(m[1].splitlines()):
              mesures[-1][keys[i % 2]].append(float(v.strip()))
      
      # 1er élément
      print(len(mesures[0]['frequences'])) # 461
      print(len(mesures[0]['amplitudes'])) # 461
      # Dernier élément
      print(len(mesures[-1]['frequences'])) # 461
      print(len(mesures[-1]['amplitudes'])) # 461
      
      # test si présence d'une valeur de fréquences dans les amplitudes
      for i in range(len(mesures)):
          for v in mesures[i]['frequences']:
              if v in mesures[i]['amplitudes']:
                  print('oups => ', v, i)
                  break
          else:
              # Sera affiché 3 fois
              print(f'Aucune valeurs identiques dans mesures[{i}]')


      Par contre si c'est simplement une inversion amplitudes et fréquences, il suffit d'inverser les valeurs du tuple keys.
      0