Como ler um arquivo de texto em uma lista ou matriz com Python

176

Estou tentando ler as linhas de um arquivo de texto em uma lista ou matriz em python. Eu só preciso acessar individualmente qualquer item da lista ou matriz depois que ele é criado.

O arquivo de texto está formatado da seguinte maneira:

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

Onde ...está acima, o arquivo de texto real possui centenas ou milhares de itens a mais.

Estou usando o código a seguir para tentar ler o arquivo em uma lista:

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

A saída que recebo é:

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

Aparentemente, ele está lendo o arquivo inteiro em uma lista de apenas um item, em vez de em uma lista de itens individuais. O que estou fazendo de errado?

user2037744
fonte
1
Apenas como uma nota. Parece que essa pergunta deve ser reformulada como ler um arquivo csv em uma lista em Python. Mas adia as intenções originais do OP há mais de 4 anos, as quais não conheço.
demongolem
1
De fato, olhando para a resposta superior, esta é uma duplicata de stackoverflow.com/questions/3277503/… .
AMC

Respostas:

135

Você precisará dividir sua string em uma lista de valores usando split()

Assim,

lines = text_file.read().split(',')
Achrome
fonte
1
Penso que esta resposta poderia ser melhorado ... Se você considerar uma multilinha .csvarquivo (como mencionado pelo OP), por exemplo, um arquivo contendo os caracteres alfabéticos 3 por linha ( a,b,c, d,e,f, etc.) e aplicar o procedimento descrito acima o que você começa é uma lista como esta: ['a', 'b', 'c\nd', 'e', ... ](observe o item 'c\nd'). Eu gostaria de acrescentar que, o problema acima, sem distorção, esse procedimento recolhe dados de linhas individuais em uma única mega-lista, geralmente não o que eu quero ao processar um arquivo de dados orientado a registros.
Gboffi
split vai deixar as novas linhas. Não faça isso, use o csvmódulo ou algum outro analisador existente
Jean-François Fabre
42

Você também pode usar numpy loadtxt como

from numpy import loadtxt
lines = loadtxt("filename.dat", comments="#", delimiter=",", unpack=False)
Thiru
fonte
1
Eu também preciso disso. Notei em um Raspberry Pi que o numpy funciona bem devagar. Para esta aplicação, reverti para abrir um arquivo e lê-lo linha por linha.
Guus
2
Isso é útil para especificar o formato também, via dtype : data-typeparâmetro. docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt.html Pandas read_csv é muito fácil de usar. Mas não vi uma maneira de especificar o formato para ele. Estava lendo carros alegóricos do meu arquivo, enquanto eu precisava de uma string. Obrigado @Thiru por mostrar o loadtxt.
Ozgur Ozturk
1
se os arquivos txt contiverem strings, o dtype deverá ser especificado, assim como linhas = loadtxt ("filename.dat", dtype = str, comentários = "#", delimitador = ",", descompactar = False)
Alex M981
19

Então você quer criar uma lista de listas ... Precisamos começar com uma lista vazia

list_of_lists = []

Em seguida, lemos o conteúdo do arquivo, linha por linha

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)

Um caso de uso comum é o de dados colunares, mas nossas unidades de armazenamento são as linhas do arquivo que lemos uma a uma, portanto, convém transpor sua lista de listas. Isso pode ser feito com o seguinte idioma

by_cols = zip(*list_of_lists)

Outro uso comum é dar um nome a cada coluna

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 você possa operar em itens de dados homogêneos

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

A maior parte do que escrevi pode ser acelerada usando o csvmódulo, da biblioteca padrão. Outro módulo de terceiros é o pandasque permite automatizar a maioria dos aspectos de uma análise de dados típica (mas possui várias dependências).


Atualização Enquanto no Python 2 zip(*list_of_lists)retorna uma lista diferente (transposta) de listas, no Python 3 a situação mudou e zip(*list_of_lists)retorna um objeto zip que não pode ser subscrito.

Se você precisar de acesso indexado, poderá usar

by_cols = list(zip(*list_of_lists))

que fornece uma lista de listas nas duas versões do Python.

Por outro lado, se você não precisa de acesso indexado e o que você deseja é apenas criar um dicionário indexado por nomes de colunas, um objeto zip é adequado ...

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
fonte
O OP disse que queria uma lista de dados de um CSV, não uma "lista de listas". Basta usar o csvmódulo ...
Blairg23
4

Esta pergunta está perguntando como ler o conteúdo do valor separado por vírgula de um arquivo em uma lista iterável:

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

A maneira mais fácil de fazer isso é com o csvmódulo da seguinte maneira:

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

Agora, você pode facilmente iterar spamreaderdessa maneira:

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

Veja a documentação para mais exemplos.

Blairg23
fonte