Cómo leer un archivo de texto en una lista o matriz con Python

176

Estoy tratando de leer las líneas de un archivo de texto en una lista o matriz en python. Solo necesito poder acceder individualmente a cualquier elemento de la lista o matriz una vez creado.

El archivo de texto tiene el siguiente formato:

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

Donde ...está arriba, el archivo de texto real tiene cientos o miles de elementos más.

Estoy usando el siguiente código para intentar leer el archivo en una lista:

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

El resultado que obtengo es:

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

Aparentemente, está leyendo el archivo completo en una lista de un solo elemento, en lugar de una lista de elementos individuales. ¿Qué estoy haciendo mal?

usuario2037744
fuente
1
Solo como una nota. Parece que esta pregunta debería reformularse como cómo leer un archivo csv en una lista en Python. Pero difiero las intenciones originales del OP hace más de 4 años, que no sé.
demongolem
1
De hecho, mirando la respuesta principal, este es un duplicado de stackoverflow.com/questions/3277503/… .
AMC

Respuestas:

135

Tendrá que dividir su cadena en una lista de valores usando split()

Entonces,

lines = text_file.read().split(',')
Achrome
fuente
1
Creo que esta respuesta podría ser mejor ... Si se tiene en cuenta una línea múltiple .csvde archivos (como se ha mencionado por el OP), por ejemplo, un archivo que contiene los caracteres alfabéticos 3 por fila ( a,b,c, d,e,f, etc.) y aplicar el procedimiento descrito anteriormente lo que se obtiene es una lista como esta: ['a', 'b', 'c\nd', 'e', ... ](tenga en cuenta el artículo 'c\nd'). Me gustaría agregar que, el problema anterior no es comprensivo, este procedimiento colapsa los datos de filas individuales en una sola megalista, generalmente no es lo que quiero al procesar un archivo de datos orientado a registros.
gboffi
Split va a salir de las nuevas líneas. No haga esto, use el csvmódulo o algún otro analizador existente
Jean-François Fabre
42

También puedes usar numpy loadtxt como

from numpy import loadtxt
lines = loadtxt("filename.dat", comments="#", delimiter=",", unpack=False)
Thiru
fuente
1
Yo también necesito esto. Me di cuenta en un Raspberry Pi que numpy funciona muy lento Para esta aplicación, volví a abrir un archivo y lo leí línea por línea.
Guus
2
Esto es útil para especificar el formato también, a través del dtype : data-typeparámetro. docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt.html Pandas read_csv es muy fácil de usar. Pero no vi una manera de especificar el formato. Estaba leyendo flotantes de mi archivo, mientras que necesitaba una cadena. Gracias @Thiru por mostrar loadtxt.
Ozgur Ozturk
1
si los archivos txt contienen cadenas, se debe especificar dtype, por lo que debe ser como lines = loadtxt ("filename.dat", dtype = str, comments = "#", delimiter = ",", unpack = False)
Alex M981
19

Entonces desea crear una lista de listas ... Necesitamos comenzar con una lista vacía

list_of_lists = []

a continuación, leemos el contenido del archivo, línea por línea

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 de uso común es el de los datos en columnas, pero nuestras unidades de almacenamiento son las filas del archivo, que hemos leído una por una, por lo que es posible que desee transponer su lista de listas. Esto se puede hacer con el siguiente modismo

by_cols = zip(*list_of_lists)

Otro uso común es dar un nombre a cada columna.

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]

para que pueda operar con elementos de datos homogéneos

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

La mayor parte de lo que he escrito se puede acelerar utilizando el csvmódulo, de la biblioteca estándar. Otro módulo de terceros es pandas, que le permite automatizar la mayoría de los aspectos de un análisis de datos típico (pero tiene una serie de dependencias).


Actualización Mientras que en Python 2 zip(*list_of_lists)devuelve una lista diferente (transpuesta) de listas, en Python 3 la situación ha cambiado y zip(*list_of_lists)devuelve un objeto zip que no es subscriptable.

Si necesita acceso indexado, puede usar

by_cols = list(zip(*list_of_lists))

eso te da una lista de listas en ambas versiones de Python.

Por otro lado, si no necesita acceso indexado y lo que desea es crear un diccionario indexado por nombres de columna, un objeto zip está bien ...

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
gboffi
fuente
El OP dijo que querían una lista de datos de un CSV, no una "lista de listas". Simplemente use el csvmódulo ...
Blairg23
4

Esta pregunta es cómo leer los contenidos de valores separados por comas de un archivo en una lista iterable:

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

La forma más fácil de hacer esto es con el csvmódulo de la siguiente manera:

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

Ahora, puedes iterar fácilmente spamreaderasí:

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

Ver documentación para más ejemplos.

Blairg23
fuente