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

Fermé
AlexM31 Messages postés 10 Date d'inscription vendredi 6 août 2021 Statut Membre Dernière intervention 30 août 2021 - 6 août 2021 à 15:34
 vortex - 30 août 2021 à 12:02
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
A voir également:

10 réponses

Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
Modifié le 6 août 2021 à 16:25
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
AlexM31 Messages postés 10 Date d'inscription vendredi 6 août 2021 Statut Membre Dernière intervention 30 août 2021
23 août 2021 à 15:41
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
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
AlexM31 Messages postés 10 Date d'inscription vendredi 6 août 2021 Statut Membre Dernière intervention 30 août 2021
23 août 2021 à 16:04
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
AlexM31 Messages postés 10 Date d'inscription vendredi 6 août 2021 Statut Membre Dernière intervention 30 août 2021 > AlexM31 Messages postés 10 Date d'inscription vendredi 6 août 2021 Statut Membre Dernière intervention 30 août 2021
23 août 2021 à 16:04
0
vortex > AlexM31 Messages postés 10 Date d'inscription vendredi 6 août 2021 Statut Membre Dernière intervention 30 août 2021
23 août 2021 à 17:45
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
AlexM31 Messages postés 10 Date d'inscription vendredi 6 août 2021 Statut Membre Dernière intervention 30 août 2021 > vortex
Modifié le 24 août 2021 à 14:07
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
Utilisateur anonyme
24 août 2021 à 13:43
Bonjour

Tu connais les expressions régulières (regex ?) ça pourrait répondre à ton besoin.
0
AlexM31 Messages postés 10 Date d'inscription vendredi 6 août 2021 Statut Membre Dernière intervention 30 août 2021
Modifié le 24 août 2021 à 14:10
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
Utilisateur anonyme
24 août 2021 à 15:01
Oui et non, ça pourrait directement extraire les données que tu cherches.
Peux tu poster un bout de fichier représentatif sur un service comme cjoint par exemple.
0
AlexM31 Messages postés 10 Date d'inscription vendredi 6 août 2021 Statut Membre Dernière intervention 30 août 2021
24 août 2021 à 15:15
Biensur,
lien cjoint pour le code : https://www.cjoint.com/c/KHynnICFrUC
lien pour le fichier .txt : https://www.cjoint.com/c/KHynoznLzfC
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
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
Utilisateur anonyme
24 août 2021 à 18:07
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
Utilisateur anonyme
24 août 2021 à 19:56
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
AlexM31 Messages postés 10 Date d'inscription vendredi 6 août 2021 Statut Membre Dernière intervention 30 août 2021
25 août 2021 à 11:08
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
Utilisateur anonyme
25 août 2021 à 11:28
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
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
AlexM31 Messages postés 10 Date d'inscription vendredi 6 août 2021 Statut Membre Dernière intervention 30 août 2021
Modifié le 27 août 2021 à 14:22
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
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
AlexM31 Messages postés 10 Date d'inscription vendredi 6 août 2021 Statut Membre Dernière intervention 30 août 2021
30 août 2021 à 09:29
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
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