Значение огромное.CSV-файл
в настоящее время я пытаюсь прочитать данные.csv файлы в Python 2.7 с до 1 миллиона строк и 200 столбцов (файлы в диапазоне от 100 МБ до 1,6 Гб). Я могу сделать это (очень медленно) для файлов с менее чем 300 000 строк, но как только я иду выше, что я получаю ошибки памяти. Мой код выглядит так:
def getdata(filename, criteria):
data=[]
for criterion in criteria:
data.append(getstuff(filename, criteron))
return data
def getstuff(filename, criterion):
import csv
data=[]
with open(filename, "rb") as csvfile:
datareader=csv.reader(csvfile)
for row in datareader:
if row[3]=="column header":
data.append(row)
elif len(data)<2 and row[3]!=criterion:
pass
elif row[3]==criterion:
data.append(row)
else:
return data
причина предложения else в функции getstuff заключается в том, что все элементы, соответствующие критерию, будут перечислены вместе в csv-файле, поэтому я оставляю цикл, когда получаю мимо них, чтобы сэкономить время.
мои вопросы:
Как я могу заставить это работать с большими файлами?
есть ли способ сделать это быстрее?
Мой компьютер имеет 8 ГБ оперативной памяти, работает под управлением 64bit Windows 7, а процессор 3,40 ГГц (не уверен, какая информация вам нужна).
Спасибо за любую помощь!
7 ответов:
Вы читаете все строки в список, а затем обрабатываете этот список. не надо.
обрабатывайте свои строки по мере их создания. Если вам нужно сначала отфильтровать данные, используйте функцию генератора:
import csv def getstuff(filename, criterion): with open(filename, "rb") as csvfile: datareader = csv.reader(csvfile) yield next(datareader) # yield the header row count = 0 for row in datareader: if row[3] == criterion: yield row count += 1 elif count: # done when having read a consecutive series of rows returnЯ также упростил ваш тест фильтра; логика такая же, но более лаконичная.
поскольку вы сопоставляете только одну последовательность строк, соответствующую критерию, вы также можете использовать:
import csv from itertools import dropwhile, takewhile def getstuff(filename, criterion): with open(filename, "rb") as csvfile: datareader = csv.reader(csvfile) yield next(datareader) # yield the header row # first row, plus any subsequent rows that match, then stop # reading altogether # Python 2: use `for row in takewhile(...): yield row` instead # instead of `yield from takewhile(...)`. yield from takewhile( lambda r: r[3] == criterion, dropwhile(lambda r: r[3] != criterion, datareader)) returnтеперь вы можете зациклить за
getstuff()напрямую. Сделайте то же самое вgetdata():def getdata(filename, criteria): for criterion in criteria: for row in getstuff(filename, criterion): yield rowтеперь цикл непосредственно над
getdata()в коде:for row in getdata(somefilename, sequence_of_criteria): # process rowвы теперь только держать одну строку в памяти, вместо ваших тысяч строк по критерию.
yieldделает функцию a функции генератора, что означает, что он не будет делать никакой работы, пока вы не начнете зацикливаться на нем.
хотя ответ Мартиджина, вероятно, лучший. Вот более интуитивный способ обработки больших файлов csv для начинающих. Это позволяет обрабатывать группы строк или фрагментов одновременно.
import pandas as pd chunksize = 10 ** 8 for chunk in pd.read_csv(filename, chunksize=chunksize): process(chunk)
Я делаю изрядное количество анализа вибрации и просматривать большие объемы данных (десятки и сотни миллионов точек). Мое тестирование показало панды.read_csv ()
недавно я пытался решить ту же проблему, но обнаружил, что пакет python pandas достаточно эффективен.
вы можете проверить здесь http://pandas.pydata.org/
Pandas-это высокопроизводительная библиотека анализа данных для больших данных.
то, что работало для меня, было и является сверхбыстрым
import pandas as pd import dask.dataframe as dd import time t=time.clock() df_train = dd.read_csv('../data/train.csv', usecols=[col1, col2]) df_train=df_train.compute() print("load train: " , time.clock()-t)
вот еще одно решение для Python3:
import csv with open(filename, "r") as csvfile: datareader = csv.reader(csvfile) count = 0 for row in datareader: if row[3] in ("column header", criterion): doSomething(row) count += 1 elif count > 2: breakздесь
datareader- это функция генератора.
генератор является хорошим решением. И на самом деле, вы можете добавить некоторое время True: в коде(перед открытием csv), что делает его итерационным для бесконечного количества циклов.
например, в наборе данных mnist:
import gzip import numpy as np BATCHSIZE = 100 DATASIZE = 1000 LOOP = DATASIZE//BATCHSIZE def mnist_generator_iterable(path, name='train_data'): if name=='train_data': while True: with gzip.open(path+'\train-images-idx3-ubyte.gz') as bytestream: bytestream.read(16) for i in range(LOOP): buf = bytestream.read(28*28*BATCHSIZE*1) trainset = np.frombuffer(buf, dtype=np.uint8).astype(np.float32) yield trainset.reshape([-1,784])
Comments