Jak wczytać plik tekstowy do listy lub tablicy w Pythonie

176

Próbuję odczytać wiersze pliku tekstowego na liście lub tablicy w Pythonie. Muszę tylko mieć indywidualny dostęp do dowolnego elementu listy lub tablicy po jej utworzeniu.

Plik tekstowy ma następujący format:

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

Tam, gdzie ...jest powyżej, rzeczywisty plik tekstowy zawiera setki lub tysiące innych elementów.

Używam następującego kodu, aby spróbować wczytać plik do listy:

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

Wynik, który otrzymuję, to:

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

Najwyraźniej jest to wczytywanie całego pliku do listy tylko jednej pozycji, a nie do listy pojedynczych pozycji. Co ja robię źle?

user2037744
źródło
1
Tylko jako notatka. Wygląda na to, że to pytanie powinno zostać przeformułowane jako jak wczytać plik csv do listy w Pythonie. Ale trzymam się pierwotnych intencji PO sprzed 4 lat, których nie znam.
demongolem
1
W rzeczywistości, patrząc na najlepszą odpowiedź, jest to duplikat stackoverflow.com/questions/3277503/… .
AMC

Odpowiedzi:

135

Będziesz musiał podzielić swój ciąg na listę wartości za pomocą split()

Więc,

lines = text_file.read().split(',')
Achrom
źródło
1
Myślę, że odpowiedź mogłaby być lepszego ... Jeśli rozważyć multilinii .csvplik (jak wspomniano przez PO), na przykład, plik zawierający znaki alfabetu 3 po wierszu ( a,b,c, d,e,fitp) i zastosować procedurę opisaną powyżej, co masz to taka lista: ['a', 'b', 'c\nd', 'e', ... ](zwróć uwagę na tę pozycję 'c\nd'). Chciałbym dodać, że powyższy problem nie jest skręcany, ta procedura zwija dane z poszczególnych wierszy w jedną mega-listę, zwykle nie jest to to, czego chcę, gdy przetwarzam plik danych zorientowanych na rekord.
gboffi
split opuści nowe linie. Nie rób tego, użyj csvmodułu lub innego istniejącego parsera
Jean-François Fabre
42

Możesz także użyć numpy loadtxt jak

from numpy import loadtxt
lines = loadtxt("filename.dat", comments="#", delimiter=",", unpack=False)
Thiru
źródło
1
Ja też tego potrzebuję. Zauważyłem na Raspberry Pi, że numpy działa bardzo wolno. W tej aplikacji powróciłem do otwarcia pliku i przeczytania go wiersz po wierszu.
Guus
2
Jest to przydatne również do określania formatu za pomocą dtype : data-typeparametru. docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt.html Pandas read_csv jest bardzo łatwy w użyciu. Ale nie widziałem sposobu, aby określić jego format. Czytał elementy typu float z mojego pliku, podczas gdy ja potrzebowałem łańcucha. Dzięki @Thiru za pokazanie loadtxt.
Ozgur Ozturk,
1
jeśli pliki txt zawierają ciągi, należy określić dtype, więc powinno wyglądać następująco: lines = loadtxt ("filename.dat", dtype = str, comments = "#", delimiter = ",",
unpack
19

Więc chcesz stworzyć listę list ... Musimy zacząć od pustej listy

list_of_lists = []

następnie czytamy zawartość pliku, wiersz po wierszu

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)

Typowym przypadkiem użycia są dane kolumnowe, ale nasze jednostki pamięci to wiersze pliku, które przeczytaliśmy jeden po drugim, więc możesz chcieć przetransponować listę list. Można to zrobić za pomocą następującego idiomu

by_cols = zip(*list_of_lists)

Innym powszechnym zastosowaniem jest nadanie nazwy każdej kolumnie

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]

aby można było operować na jednorodnych elementach danych

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

Większość tego, co napisałem, można przyspieszyć za pomocą csvmodułu, z biblioteki standardowej. Innym zewnętrznym modułem jest pandas, który pozwala zautomatyzować większość aspektów typowej analizy danych (ale ma wiele zależności).


Aktualizacja Podczas gdy w Pythonie 2 zip(*list_of_lists)zwraca inną (transponowaną) listę list, w Pythonie 3 sytuacja uległa zmianie i zip(*list_of_lists)zwraca obiekt zip, który nie jest indeksowany.

Jeśli potrzebujesz dostępu indeksowanego, możesz użyć

by_cols = list(zip(*list_of_lists))

to daje listę list w obu wersjach Pythona.

Z drugiej strony, jeśli nie potrzebujesz dostępu do indeksów, a chcesz tylko zbudować słownik indeksowany według nazw kolumn, obiekt zip jest w porządku ...

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
źródło
OP powiedział, że chce listy danych z pliku CSV, a nie „listy list”. Po prostu użyj csvmodułu ...
Blairg23
4

To pytanie dotyczy tego, jak odczytać zawartość wartości oddzielonych przecinkami z pliku na listę iterowalną:

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

Najłatwiej to zrobić za pomocą csvmodułu w następujący sposób:

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

Teraz możesz łatwo iterować w spamreaderten sposób:

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

Więcej przykładów można znaleźć w dokumentacji .

Blairg23
źródło