Как читать файл csv объемом 6 ГБ с помощью pandas

Я пытаюсь прочитать большой файл csv (aprox. 6 ГБ) в pandas, и я получаю следующую ошибку памяти:

MemoryError                               Traceback (most recent call last)
<ipython-input-58-67a72687871b> in <module>()
----> 1 data=pd.read_csv('aphro.csv',sep=';')

C:\Python27\lib\site-packages\pandas\io\parsers.pyc in parser_f(filepath_or_buffer, sep, dialect, compression, doublequote, escapechar, quotechar, quoting, skipinitialspace, lineterminator, header, index_col, names, prefix, skiprows, skipfooter, skip_footer, na_values, na_fvalues, true_values, false_values, delimiter, converters, dtype, usecols, engine, delim_whitespace, as_recarray, na_filter, compact_ints, use_unsigned, low_memory, buffer_lines, warn_bad_lines, error_bad_lines, keep_default_na, thousands, comment, decimal, parse_dates, keep_date_col, dayfirst, date_parser, memory_map, nrows, iterator, chunksize, verbose, encoding, squeeze, mangle_dupe_cols, tupleize_cols, infer_datetime_format)
    450                     infer_datetime_format=infer_datetime_format)
    451 
--> 452         return _read(filepath_or_buffer, kwds)
    453 
    454     parser_f.__name__ = name

C:\Python27\lib\site-packages\pandas\io\parsers.pyc in _read(filepath_or_buffer, kwds)
    242         return parser
    243 
--> 244     return parser.read()
    245 
    246 _parser_defaults = {

C:\Python27\lib\site-packages\pandas\io\parsers.pyc in read(self, nrows)
    693                 raise ValueError('skip_footer not supported for iteration')
    694 
--> 695         ret = self._engine.read(nrows)
    696 
    697         if self.options.get('as_recarray'):

C:\Python27\lib\site-packages\pandas\io\parsers.pyc in read(self, nrows)
   1137 
   1138         try:
-> 1139             data = self._reader.read(nrows)
   1140         except StopIteration:
   1141             if nrows is None:

C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader.read (pandas\parser.c:7145)()

C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader._read_low_memory (pandas\parser.c:7369)()

C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader._read_rows (pandas\parser.c:8194)()

C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader._convert_column_data (pandas\parser.c:9402)()

C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader._convert_tokens (pandas\parser.c:10057)()

C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader._convert_with_dtype (pandas\parser.c:10361)()

C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser._try_int64 (pandas\parser.c:17806)()

MemoryError: 

Любая помощь по этому поводу?

Ответ 1

Ошибка показывает, что на машине недостаточно памяти для одновременного считывания всего CSV в DataFrame. Предполагая, что вам не нужен весь набор данных в памяти одновременно, один из способов избежать этой проблемы - обработать CSV в чанках (указав параметр chunksize):

chunksize = 10 ** 6
for chunk in pd.read_csv(filename, chunksize=chunksize):
    process(chunk)

Параметр chucksize указывает количество строк в блоке. (chunksize, последний блок может содержать меньше строк, чем chunksize.)

Ответ 2

Чанкинг не всегда должен быть первым портом захода для этой проблемы.

  1. Размер файла большой из-за повторяющихся нечисловых данных или нежелательных столбцов?

    Если это так, вы можете иногда наблюдать значительную экономию памяти, считывая столбцы как категории и выбирая необходимые столбцы с помощью параметра pd.read_csv usecols.

  2. Ваш рабочий процесс требует нарезки, манипуляции, экспорта?

    Если это так, вы можете использовать dask.dataframe для нарезки, выполнения своих вычислений и многократного экспорта. Чанкинг выполняется dask без вывода сообщений, который также поддерживает подмножество API pandas.

  3. Если ничего не помогает, читайте построчно через чанки.

    Кусок через панд или csv-библиотеку в качестве последнего средства.

Ответ 3

Я продолжал:

chunks=pd.read_table('aphro.csv',chunksize=1000000,sep=';',\
       names=['lat','long','rf','date','slno'],index_col='slno',\
       header=None,parse_dates=['date'])

df=pd.DataFrame()
%time df=pd.concat(chunk.groupby(['lat','long',chunk['date'].map(lambda x: x.year)])['rf'].agg(['sum']) for chunk in chunks)

Ответ 4

Для больших данных я рекомендую использовать библиотеку "dask"
например:

# Dataframes implement the Pandas API
import dask.dataframe as dd
df = dd.read_csv('s3://.../2018-*-*.csv')

Ответ 5

Вышеупомянутый ответ уже удовлетворяет теме. В любом случае, если вам нужны все данные в памяти - посмотрите bcolz. Его сжатие данных в памяти. У меня был действительно хороший опыт. Но его недостающее количество pandas функций

Изменить: я получил коэффициент сжатия около 1/10 или размер оригинала, я думаю, конечно, в зависимости от типа данных. Важными недостающими функциями были агрегаты.

Ответ 6

Вы можете читать данные как куски и сохранять каждый кусок как рассол.

import pandas as pd 
import pickle

in_path = "" #Path where the large file is
out_path = "" #Path to save the pickle files to
chunk_size = 400000 #size of chunks relies on your available memory
separator = "~"

reader = pd.read_csv(in_path,sep=separator,chunksize=chunk_size, 
                    low_memory=False)    


for i, chunk in enumerate(reader):
    out_file = out_path + "/data_{}.pkl".format(i+1)
    with open(out_file, "wb") as f:
        pickle.dump(chunk,f,pickle.HIGHEST_PROTOCOL)

На следующем шаге вы читаете в рассолах и добавляете каждый рассол к желаемому фрейму данных.

import glob
pickle_path = "" #Same Path as out_path i.e. where the pickle files are

data_p_files=[]
for name in glob.glob(pickle_path + "/data_*.pkl"):
   data_p_files.append(name)


df = pd.DataFrame([])
for i in range(len(data_p_files)):
    df = df.append(pd.read_pickle(data_p_files[i]),ignore_index=True)

Ответ 8

Функция read_csv и read_table почти то же самое. Но вы должны назначить разделитель ",", когда вы используете функцию read_table в своей программе.

def get_from_action_data(fname, chunk_size=100000):
    reader = pd.read_csv(fname, header=0, iterator=True)
    chunks = []
    loop = True
    while loop:
        try:
            chunk = reader.get_chunk(chunk_size)[["user_id", "type"]]
            chunks.append(chunk)
        except StopIteration:
            loop = False
            print("Iteration is stopped")

    df_ac = pd.concat(chunks, ignore_index=True)

Ответ 9

Вы можете попробовать sframe, который имеет тот же синтаксис, что и pandas, но позволяет вам манипулировать файлами, которые больше, чем ваша оперативная память.

Ответ 10

Если вы используете pandas, читайте большой файл в куске, а затем приводите строку за строкой, вот что я сделал

import pandas as pd

def chunck_generator(filename, header=False,chunk_size = 10 ** 5):
   for chunk in pd.read_csv(filename,delimiter=',', iterator=True, chunksize=chunk_size, parse_dates=[1] ): 
        yield (chunk)

def _generator( filename, header=False,chunk_size = 10 ** 5):
    chunk = chunck_generator(filename, header=False,chunk_size = 10 ** 5)
    for row in chunk:
        yield row

if __name__ == "__main__":
filename = r'file.csv'
        generator = generator(filename=filename)
        while True:
           print(next(generator))

Ответ 11

Вот следующий пример:

chunkTemp = []
queryTemp = []
query = pd.DataFrame()

for chunk in pd.read_csv(file, header=0, chunksize=<your_chunksize>, iterator=True, low_memory=False):

    #REPLACING BLANK SPACES AT COLUMNS' NAMES FOR SQL OPTIMIZATION
    chunk = chunk.rename(columns = {c: c.replace(' ', '') for c in chunk.columns})

    #YOU CAN EITHER: 
    #1)BUFFER THE CHUNKS IN ORDER TO LOAD YOUR WHOLE DATASET 
    chunkTemp.append(chunk)

    #2)DO YOUR PROCESSING OVER A CHUNK AND STORE THE RESULT OF IT
    query = chunk[chunk[<column_name>].str.startswith(<some_pattern>)]   
    #BUFFERING PROCESSED DATA
    queryTemp.append(query)

#!  NEVER DO pd.concat OR pd.DataFrame() INSIDE A LOOP
print("Database: CONCATENATING CHUNKS INTO A SINGLE DATAFRAME")
chunk = pd.concat(chunkTemp)
print("Database: LOADED")

#CONCATENATING PROCESSED DATA
query = pd.concat(queryTemp)
print(query)

Ответ 12

В дополнение к ответам выше, для тех, кто хочет обработать CSV, а затем экспортировать в csv, паркет или SQL, d6tstack - еще один хороший вариант. Вы можете загружать несколько файлов и обрабатывать изменения схемы данных (добавленные/удаленные столбцы). Уже встроена основная поддержка.

def apply(dfg):
    # do stuff
    return dfg

c = d6tstack.combine_csv.CombinerCSV([bigfile.csv], apply_after_read=apply, sep=',', chunksize=1e6)

# or
c = d6tstack.combine_csv.CombinerCSV(glob.glob('*.csv'), apply_after_read=apply, chunksize=1e6)

# output to various formats, automatically chunked to reduce memory consumption
c.to_csv_combine(filename='out.csv')
c.to_parquet_combine(filename='out.pq')
c.to_psql_combine('postgresql+psycopg2://usr:[email protected]/db', 'tablename') # fast for postgres
c.to_mysql_combine('mysql+mysqlconnector://usr:[email protected]/db', 'tablename') # fast for mysql
c.to_sql_combine('postgresql+psycopg2://usr:[email protected]/db', 'tablename') # slow but flexible

Ответ 13

В случае, если кто-то все еще ищет что-то подобное, я обнаружил, что эта новая библиотека под названием modin может помочь. Он использует распределенные вычисления, которые могут помочь с чтением. Здесь хорошая статья, сравнивающая его функциональность с пандами. Он по существу использует те же функции, что и панды.

import modin.pandas as pd
pd.read_csv(CSV_FILE_NAME)

Ответ 14

У меня также есть эта проблема с памятью при чтении данных CSV. Файл имеет ок. 10.000.000 строк и 5 столбцов (это большой 0,5 ГБ). Я пробовал несколько вариантов кода, которые можно найти в Интернете, но, тем не менее, я всегда получаю ошибку памяти. Эта ошибка памяти всегда возникает при ок. 932 МБ использования командной строки. Он никогда не пересекает 1 ГБ, хотя общее использование оперативной памяти составляет 70% или менее. Если я уменьшу файл вручную до 1.019.000 строк кода, проблем не будет. И проблема в том, что мне нужен целый файл для его анализа.

Вот моя последняя реализация чтения файла CSV:

fileName = r'data.csv'
chunks = pd.read_csv(fileName, chunksize=1000)
dsf = pd.concat(chunks)