1
votes

Ouvrir et lire un fichier texte délimité par des espaces

J'ai un fichier txt séparé par des espaces comme suit:

import re
list_b = []
list_d = []

with open('TA103019.95.txt', 'r') as f:
    for line in f:
        list_line = re.findall(r"[\d.\d+']+", line)
        list_b.append(float(list_line[1])) #appends second column
        list_d.append(float(list_line[3])) #appends fourth column

print list_b
print list_d

Je veux calculer la moyenne de Tmax et Tmin séparément. Mais, j'ai du mal à lire le fichier txt. J'ai essayé ce lien comme . p>

2004          Temperature for KATHMANDU AIRPORT       
        Tmax  Tmin
     1  18.8   2.4 
     2  19.0   1.1 
     3  18.3   1.7 
     4  18.3   1.0 
     5  17.8   1.3 

Mais cela me donne une erreur: IndexError: index de la liste hors limites qu'est-ce qui ne va pas ici?


0 commentaires

6 Réponses :


0
votes

Simplifiez-vous la vie et évitez ce problème.

Vous lisez peut-être la ligne d'en-tête par erreur? Si le format du fichier est fixe, je "brûle" généralement la ligne d'en-tête avec une ligne lue avant de démarrer la boucle comme:

with open(file_name, 'r') as f:
    f.readline()  # burn the header row
    for line in f:
        tokens = line.strip().split(' ')   # tokenize the row based on spaces

Ensuite, vous avez une liste de jetons, qui seront des chaînes que vous aurez besoin de convertir en int ou float ou autre et à partir de là!

Mettez quelques instructions d'impression pour voir ce que vous prenez ...


0 commentaires

2
votes

Un moyen simple de résoudre ce problème consiste à utiliser Fonction split () . Bien sûr, vous devez supprimer les deux premières lignes:

['1', '18.8', '2.4']
['2', '19.0', '1.1']
['3', '18.3', '1.7']
['4', '18.3', '1.0']
['5', '17.8', '1.3']

Vous obtenez:

with io.open("path/to/file.txt", mode="r", encoding="utf-8") as f:
    next(f)
    next(f)
    for line in f:
        print(line.split())

Citant la documentation:

Si sep n'est pas spécifié ou est Aucun , un algorithme de fractionnement différent est appliqué: les exécutions d'espaces blancs consécutifs sont considérées comme un seul séparateur, et le résultat ne contiendra aucun des chaînes vides au début ou à la fin si la chaîne comporte un espace blanc au début ou à la fin.


2 commentaires

Cela me donne l'erreur NameError: le nom 'io' n'est pas défini


Utilisez import io



0
votes

Est-il possible que votre fichier soit délimité par des tabulations?

Pour les délimités par des tabulations:

with open('TA103019.95.txt', 'r') as f:
    for idx, line in enumerate(f):
        if idx > 1:                    
            cols = line.split('\t'): #for space delimited change '\t' to ' '
            tmax = float(col[1])
            tmin = float(col[2])
            #calc mean

            mean = (tmax + tmin) / 2
            #not sure what you want to do with the result


2 commentaires

Cela me donne l'erreur IndexError: list index out of range


C'est parce que nous n'avons pas traité les deux premières lignes qui ne sont pas des données.



1
votes

Comme indiqué ici , re.findall code > répertorie toutes les correspondances de votre expression régulière. l'expression que vous définissez ne correspond à rien dans votre fichier et vous obtenez donc un tableau vide, ce qui entraîne l'erreur lorsque vous essayez d'accéder à list_line [1] .

  • l'expression que vous souhaitez associer à la base de ce fichier serait r "\ d + \. \ d +" , correspondant à tout nombre décimal avec au moins un chiffre avant le point décimal, ce point décimal au moins un chiffre après
  • même cette expression ne correspondra à rien dans les deux premières lignes, vous voudrez donc vérifier les tableaux vides
  • le résultat ne connaît aucune colonne, juste des correspondances du modèle, et il y aura deux correspondances pour chaque ligne de données - vous voudrez des indizes 0 et 1

donc: importer re list_b = [] list_d = []

with open('TA103019.95.txt', 'r') as f:
    for line in f:
        list_line = re.findall(r'\d+\.\d+', line)
        if len(list_line) == 2 :
            list_b.append(float(list_line[0])) #appends second column
            list_d.append(float(list_line[1])) #appends fourth column

print list_b
print list_d


0 commentaires

1
votes
import re
list_b = []
list_d = []

with open('TA103019.95.txt', 'r') as f:
    for line in f:
        # regex is corrected to match the decimal values only
        list_line = re.findall(r"\d+\.\d+", line) 

        # error condition handled where the values are not found 
        if len(list_line) < 2: 
            continue

        # indexes are corrected below
        list_b.append(float(list_line[0])) #appends second column
        list_d.append(float(list_line[1])) #appends fourth column

print list_b
print list_d
I have added my answer with some comments in the code itself.You were getting the Index out of range error because your list_line was having only a single element(i.e. 2004 in the first line of file) and you were trying to access the 1st and 3rd index of the list_line.

0 commentaires

1
votes

Solution complète

def readit(file_name,start_line = 2): # start_line - where your data starts (2 line mean 3rd line, because we start from 0th line) 
    with open(file_name,'r') as f:
        data = f.read().split('\n')
    data = [i.split(' ') for i in data[start_line:]]
    for i in range(len(data)):
        row = [(sub) for sub in data[i] if len(sub)!=0]
        yield int(row[0]),float(row[1]),float(row[2])


iterator = readit('TA103019.95.txt')


index, tmax, tmin = zip(*iterator)


mean_Tmax = sum(tmax)/len(tmax)
mean_Tmin = sum(tmin)/len(tmin)
print('Mean Tmax: ',mean_Tmax)
print('Mean Tmnin: ',mean_Tmin)

>>> ('Mean Tmax: ', 18.439999999999998)
>>> ('Mean Tmnin: ', 1.5)

Merci à Dan D. pour une solution plus élégante


2 commentaires

Vous auriez pu sauter deux lignes en appelant next (f) deux fois, puis en un seul pour la ligne en f: vous auriez pu analyser et produire chaque ligne. Cela éliminerait à la fois les données des listes et le traitement. Et la transposition peut être effectuée avec zip comme index, tmax, tmin = zip (* iterator) .


Merci. J'ai partiellement édité la solution, pas complètement (je ne savais pas trop comment implémenter next (f) mais je ne voulais pas non plus y passer trop de temps). N'hésitez pas à modifier la réponse.