2
votes

Comment puis-je lire un fichier csv uniquement après avoir trouvé un certain modèle avec Python?

J'ai donc plusieurs fichiers csv qui représentent des données, dont chacun peut avoir différentes lignes de commentaires initiaux

import os
import glob
import csv

def read_multicolumn_csv_files_into_dictionary(folderpath, dictionary):
    filepath = folderpath + '*.csv'
    files = sorted(glob.glob(filepath))
    for file in files:
        data_set = file.replace(folderpath, '').replace('.csv', '')
        dictionary[data_set] = {}
        with open(file, 'r') as data_file:
            data_pipe = csv.DictReader(data_file)
            dictionary[data_set]['pt'] = []
            dictionary[data_set]['sigma'] = []
            for row in data_pipe:
                dictionary[data_set]['pt'].append(float(row['PT [GEV]']))
                dictionary[data_set]['sigma'].append(float(row['D2(SIG)/DYRAP/DPT [NB/GEV]']))
    return dictionary

Je voudrais lire uniquement les données pertinentes et leurs en-têtes, qui commencent par la ligne

PT [GEV], PT [GEV] LOW, PT [GEV] HIGH, D2(SIG)/DYRAP/DPT [NB/GEV]

Par conséquent, la stratégie à laquelle je penserais est de trouver le modèle PT [GEV] et de commencer à lire à partir de là.

Cependant, je ne sais pas comment y parvenir en Python, quelqu'un pourrait-il m'aider à ce sujet?

Merci d'avance!


Au fait, la fonction que j'ai actuellement est

table_doi: 10.17182/hepdata.52402.v1/t7
name: Table 7
...
ABS(YRAP), < 0.1
SQRT(S) [GeV], 1960
PT [GEV], PT [GEV] LOW, PT [GEV] HIGH, D2(SIG)/DYRAP/DPT [NB/GEV]
67, 62, 72, 6.68
...
613.5, 527, 700, 1.81E-07

qui ne fonctionne que si je supprime manuellement ces commentaires initiaux dans les fichiers csv.


0 commentaires

5 Réponses :


1
votes

En supposant que chaque fichier a une ligne commençant par PT [GEV] :

import os
import pandas as pd

...
csvs = []
for file in files:
    with open(file) as f:
        for i, l in enumerate(f):
            if l.startswith('PT [GEV]'):
                csvs.append(pd.read_csv(file, skiprows = i))
                break
df = pd.concat(csvs)


0 commentaires

1
votes

Essayez ceci où il recherchera la ligne qui contient PT [GEV] et s'il trouve le contient, il changera le m pour être vrai et commencera à ajouter le reste de la date à la liste:

import csv

contain= 'PT [GEV]'
List=[]
m=false
with open('Users.csv', 'rt') as f:
     reader = csv.reader(f, delimiter=',') 
     for row in reader:
          for field in row:
              if field == contain:
              m=true
          if m==true:
             List.append(row)            


3 commentaires

Ça a marché! Il renverrait une liste de liste, comment pensez-vous que je pourrais la transmettre à csv.DictReader ? Ou avez-vous une meilleure idée de le manipuler?


vous pouvez facilement convertir la liste en dictionnaire voir ce stackoverflow.com/questions/6900955/...


Merci, je vais essayer, désolé pour la réponse tardive.



1
votes

Vous pouvez utiliser la méthode file.tell pour enregistrer la position du pointeur de fichier pendant que vous lisez et ignorez les lignes jusqu'à ce que vous trouviez la ligne d'en-tête, à quel point vous pouvez utiliser la méthode file.seek pour réinitialiser le pointeur de fichier au début de la ligne d'en-tête pour que csv.DictReader puisse analyser le reste du fichier comme CSV valide:

with open(file, 'r') as data_file:
    while True:
        position = data_file.tell()
        line = next(data_file)
        if line.count(',') == 3: # or whatever condition your header line satisfies
            data_file.seek(position) # reset file pointer to the beginning of the header line
            break
    data_pipe = csv.DictReader(data_file)
    ...


1 commentaires

C'est une belle façon de le faire! J'ai 20 entrées pour les données réelles, donc j'écris if line.count(',') == 19: mais je récupère un dictionnaire vide. J'ai donc essayé d'imprimer la line avant la if déclaration et il ne semble que le while est mis fin à la boucle une fois que le programme a trouvé la ligne d' en- tête réelle. Pensez-vous que le problème vient du passage de data_file à data_pipe ?



0
votes

Je créerais simplement une fonction d'aide pour amener votre lecteur csv au premier enregistrement:

def remove_comments_from_file():

    file_name = "super_secret_file.csv"
    file = open(file_name, 'rU')

    csv_read_file = csv.reader(file)        

    for row in csv_read_file:
        if row[0] == "PT [GEV]"
            break

    return csv_read_file

Quelque chose dans ce sens, lorsque le lecteur csv est renvoyé, il démarrera à votre premier enregistrement (dans cet exemple - 67, 62, 72, 6.68)


2 commentaires

Merci pour votre réponse, mais comment manipuler le csv_read_file renvoyé? J'ai essayé de le transmettre à la fonction mais il serait reconnu comme NoneType , puis j'ai essayé de l'imprimer, mais la seule chose qui est montrée est <_csv.reader object at 0x1190d44b0> .


Au fait, il y a des lignes vides qui pourraient poser des problèmes, j'ai donc ajouté une instruction if row != []: Qui traite de cela.



2
votes

le paiement startswith . Vous pouvez également trouver des explications détaillées ici. https://cmdlinetips.com/2018/01/3-ways-to-read-a-file-and-skip-initial-comments-in-python/


1 commentaires

J'ai déjà lu cette page Web, cependant, ce que j'essaie de faire est de trouver PT [GEV] et de tout lire au-delà de ce point, alors que les lignes au-delà ne commencent pas nécessairement par PT [GEV] .