Значение огромное.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-файле, поэтому я оставляю цикл, когда получаю мимо них, чтобы сэкономить время.



мои вопросы:




  1. Как я могу заставить это работать с большими файлами?


  2. есть ли способ сделать это быстрее?



Мой компьютер имеет 8 ГБ оперативной памяти, работает под управлением 64bit Windows 7, а процессор 3,40 ГГц (не уверен, какая информация вам нужна).



Спасибо за любую помощь!

613   7  

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

    Ничего не найдено.