Come leggere un file di testo in un elenco o un array con Python


176

Sto cercando di leggere le righe di un file di testo in un elenco o array in Python. Devo solo essere in grado di accedere individualmente a qualsiasi elemento dell'elenco o dell'array dopo che è stato creato.

Il file di testo è formattato come segue:

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

Dove ...è sopra, il file di testo effettivo ha centinaia o migliaia di elementi in più.

Sto usando il seguente codice per provare a leggere il file in un elenco:

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

L'output che ottengo è:

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

Apparentemente sta leggendo l'intero file in un elenco di un solo elemento, anziché in un elenco di singoli elementi. Che cosa sto facendo di sbagliato?


1
Proprio come una nota. Sembra che questa domanda debba essere riformulata come leggere un file CSV in un elenco in Python. Ma rinvio alle intenzioni originali del PO oltre 4 anni fa che non conosco.
demongolem,



1
In effetti, guardando la risposta migliore, questo è un duplicato di stackoverflow.com/questions/3277503/… .
AMC,

Risposte:


135

Dovrai dividere la stringa in un elenco di valori utilizzando split()

Così,

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

1
Credo che questa risposta avrebbe potuto essere migliore ... Se si considera una multilinea .csvdi file (come detto dal PO), ad esempio, un file contenente i caratteri alfabetici 3 per riga ( a,b,c, d,e,f, ecc) e applicare la procedura descritta sopra quello che si ottiene è un elenco come questo: ['a', 'b', 'c\nd', 'e', ... ](notare l'elemento 'c\nd'). Vorrei aggiungere che, nonostante il problema sopra riportato, questa procedura comprime i dati delle singole righe in un unico mega-elenco, di solito non è quello che voglio quando elaboro un file di dati orientato ai record.
gboffi,

split lascerà le nuove righe. Non farlo, usa il csvmodulo o qualche altro parser esistente
Jean-François Fabre

42

Puoi anche usare numpy loadtxt come

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

1
Ne ho bisogno anch'io. Ho notato su un Raspberry Pi che l'intorpidimento funziona molto lentamente. Per questa applicazione sono tornato ad aprire un file e leggerlo riga per riga.
Guus,

2
Ciò è utile anche per specificare il formato, tramite dtype : data-typeparametro. docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt.html Panda read_csv è molto facile da usare. Ma non ho visto un modo per specificare il formato per esso. Stava leggendo float dal mio file, mentre avevo bisogno di stringa. Grazie @Thiru per aver mostrato loadtxt.
Ozgur Ozturk,

1
se i file txt contengono stringhe, è necessario specificare dtype, quindi dovrebbe essere come lines = loadtxt ("nomefile.dat", dtype = str, commenti = "#", delimitatore = ",", unpack = False)
Alex M981

19

Quindi vuoi creare un elenco di elenchi ... Dobbiamo iniziare con un elenco vuoto

list_of_lists = []

poi, leggiamo il contenuto del file, riga per riga

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 caso d'uso comune è quello dei dati colonnari, ma le nostre unità di archiviazione sono le righe del file, che abbiamo letto una per una, quindi potresti voler trasporre il tuo elenco di elenchi. Questo può essere fatto con il seguente linguaggio

by_cols = zip(*list_of_lists)

Un altro uso comune è quello di assegnare un nome a ciascuna colonna

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]

in modo da poter operare su elementi di dati omogenei

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

Gran parte di ciò che ho scritto può essere accelerato utilizzando il csvmodulo, dalla libreria standard. Un altro modulo di terze parti è pandas, che ti consente di automatizzare la maggior parte degli aspetti di una tipica analisi dei dati (ma ha una serie di dipendenze).


Aggiornamento Mentre in Python 2 zip(*list_of_lists)restituisce un elenco di elenchi (trasposto) diverso, in Python 3 la situazione è cambiata e zip(*list_of_lists)restituisce un oggetto zip non sottoscrivibile.

Se hai bisogno di accesso indicizzato puoi usare

by_cols = list(zip(*list_of_lists))

che ti dà un elenco di liste in entrambe le versioni di Python.

D'altra parte, se non hai bisogno di accesso indicizzato e quello che vuoi è solo costruire un dizionario indicizzato dai nomi delle colonne, un oggetto zip va bene ...

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

L'OP ha affermato di volere un elenco di dati da un CSV, non un "elenco di elenchi". Basta usare il csvmodulo ...
Blairg23

4

Questa domanda sta chiedendo come leggere il contenuto del valore separato da virgole da un file in un elenco iterabile:

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

Il modo più semplice per farlo è con il csvmodulo come segue:

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

Ora puoi facilmente iterare in spamreaderquesto modo:

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

Vedere la documentazione per ulteriori esempi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.