Comment lire un fichier texte dans une liste ou un tableau avec Python


176

J'essaie de lire les lignes d'un fichier texte dans une liste ou un tableau en python. J'ai juste besoin de pouvoir accéder individuellement à n'importe quel élément de la liste ou du tableau après sa création.

Le fichier texte est formaté comme suit:

0,0,200,0,53,1,0,255,...,0.

Là où le ...est ci-dessus, le fichier texte réel contient des centaines ou des milliers d'éléments supplémentaires.

J'utilise le code suivant pour essayer de lire le fichier dans une liste:

text_file = open("filename.dat", "r")
lines = text_file.readlines()
print lines
print len(lines)
text_file.close()

Le résultat que j'obtiens est:

['0,0,200,0,53,1,0,255,...,0.']
1

Apparemment, il lit le fichier entier dans une liste d'un seul élément, plutôt que dans une liste d'éléments individuels. Qu'est-ce que je fais mal?


1
Juste comme une note. Il semble que cette question devrait être reformulée comme comment lire un fichier csv dans une liste en Python. Mais je m'en remets aux intentions initiales du PO il y a plus de 4 ans que je ne connais pas.
demongolem



1
En fait, en regardant la première réponse, il s'agit d'un double de stackoverflow.com/questions/3277503/… .
AMC

Réponses:


135

Vous devrez diviser votre chaîne en une liste de valeurs en utilisant split()

Alors,

lines = text_file.read().split(',')

1
Je pense que cette réponse pourrait être améliorée ... Si vous considérez comme un multiligne .csvfichier (comme mentionné par l'OP), par exemple, un fichier contenant les caractères alphabétiques 3 par ligne ( a,b,c, d,e,f, etc.) et appliquer la procédure décrite ci - dessus ce que vous obtenez est une liste comme celle-ci: ['a', 'b', 'c\nd', 'e', ... ](notez l'élément 'c\nd'). Je voudrais ajouter que, le problème ci-dessus ne se dérobant pas, cette procédure réduit les données de lignes individuelles dans une seule méga-liste, généralement pas ce que je veux lors du traitement d'un fichier de données orienté enregistrement.
gboffi

split va quitter les nouvelles lignes. Ne faites pas cela, utilisez un csvmodule ou un autre analyseur existant
Jean-François Fabre

43

Vous pouvez également utiliser numpy loadtxt comme

from numpy import loadtxt
lines = loadtxt("filename.dat", comments="#", delimiter=",", unpack=False)

1
J'ai besoin de ça aussi. J'ai remarqué sur un Raspberry Pi que numpy fonctionne très lentement. Pour cette application, je suis revenu pour ouvrir un fichier et le lire ligne par ligne.
Guus le

2
Ceci est également utile pour spécifier le format, via le dtype : data-typeparamètre. docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt.html Pandas read_csv est très facile à utiliser. Mais je n'ai pas vu de moyen de spécifier le format pour cela. Il lisait des flottants de mon fichier, alors que j'avais besoin d'une chaîne. Merci @Thiru pour avoir montré loadtxt.
Ozgur Ozturk

1
si les fichiers txt contiennent des chaînes, alors dtype doit être spécifié, donc il doit être comme lines = loadtxt ("filename.dat", dtype = str, comments = "#", delimiter = ",", unpack = False)
Alex M981

19

Vous voulez donc créer une liste de listes ... Nous devons commencer par une liste vide

list_of_lists = []

ensuite, nous lisons le contenu du fichier, ligne par ligne

with open('data') as f:
    for line in f:
        inner_list = [elt.strip() for elt in line.split(',')]
        # in alternative, if you need to use the file content as numbers
        # inner_list = [int(elt.strip()) for elt in line.split(',')]
        list_of_lists.append(inner_list)

Un cas d'utilisation courant est celui des données en colonnes, mais nos unités de stockage sont les lignes du fichier, que nous avons lues une par une, vous pouvez donc vouloir transposer votre liste de listes. Cela peut être fait avec l'idiome suivant

by_cols = zip(*list_of_lists)

Une autre utilisation courante est de donner un nom à chaque colonne

col_names = ('apples sold', 'pears sold', 'apples revenue', 'pears revenue')
by_names = {}
for i, col_name in enumerate(col_names):
    by_names[col_name] = by_cols[i]

afin de pouvoir opérer sur des éléments de données homogènes

 mean_apple_prices = [money/fruits for money, fruits in
                     zip(by_names['apples revenue'], by_names['apples_sold'])]

La plupart de ce que j'ai écrit peut être accéléré en utilisant le csvmodule, de la bibliothèque standard. Un autre module tiers est pandas, qui vous permet d'automatiser la plupart des aspects d'une analyse de données typique (mais a un certain nombre de dépendances).


Mise à jour Alors que dans Python 2 zip(*list_of_lists)renvoie une liste différente (transposée) de listes, dans Python 3, la situation a changé et zip(*list_of_lists)renvoie un objet zip qui n'est pas en indice.

Si vous avez besoin d'un accès indexé, vous pouvez utiliser

by_cols = list(zip(*list_of_lists))

qui vous donne une liste de listes dans les deux versions de Python.

D'un autre côté, si vous n'avez pas besoin d'un accès indexé et que vous voulez simplement créer un dictionnaire indexé par noms de colonnes, un objet zip convient parfaitement ...

file = open('some_data.csv')
names = get_names(next(file))
columns = zip(*((x.strip() for x in line.split(',')) for line in file)))
d = {}
for name, column in zip(names, columns): d[name] = column

Le PO a déclaré vouloir une liste de données à partir d'un CSV, pas une "liste de listes". Il suffit d'utiliser le csvmodule ...
Blairg23

4

Cette question demande comment lire le contenu des valeurs séparées par des virgules d'un fichier dans une liste itérable:

0,0,200,0,53,1,0,255,...,0.

Le moyen le plus simple de le faire est d'utiliser le csvmodule comme suit:

import csv
with open('filename.dat', newline='') as csvfile:
    spamreader = csv.reader(csvfile, delimiter=',')

Maintenant, vous pouvez facilement répéter spamreadercomme ceci:

for row in spamreader:
    print(', '.join(row))

Voir la documentation pour plus d'exemples.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.