MemoryError при больших слияниях с pandas в Python

Я использую pandas для слияния outer в наборе из примерно 1000-2000 файлов CSV. Каждый CSV файл имеет столбец идентификатора id, который разделяется между всеми файлами CSV, но каждый файл имеет уникальный набор столбцов из 3-5 столбцов. В каждом файле содержится около 20000 уникальных строк id. Все, что я хочу сделать, это объединить их вместе, объединив все новые столбцы и используя столбец id в качестве индекса слияния.

Я делаю это с помощью простого вызова merge:

merged_df = first_df # first csv file dataframe
for next_filename in filenames:
   # load up the next df
   # ...
   merged_df = merged_df.merge(next_df, on=["id"], how="outer")

Проблема в том, что с почти 2000 CSV файлами я получаю MemoryError в операции merge, созданной pandas. Я не уверен, что это ограничение из-за проблемы в операции слияния?

Окончательный блок данных будет содержать 20 000 строк и примерно (2000 х 3) = 6000 столбцов. Это большой, но недостаточно большой, чтобы потреблять всю память на компьютере, который я использую, который имеет более 20 ГБ ОЗУ. Этот размер слишком большой для pandas манипуляции? Должен ли я использовать что-то вроде sqlite? Есть ли что-то, что я могу изменить в операции merge, чтобы он работал над этим масштабом?

спасибо.

Ответ 1

Я думаю, что вы получите лучшую производительность, используя concat (который действует как внешнее соединение):

dfs = (pd.read_csv(filename).set_index('id') for filename in filenames)
merged_df = pd.concat(dfs, axis=1)

Это означает, что вы выполняете только одну операцию слияния, а не одну для каждого файла.

Ответ 2

Я встретил ту же ошибку в 32-разрядной версии, используя read_csv с файлом 1 ГБ. Попробуйте 64-битную версию и, надеюсь, решит проблему с ошибкой памяти.

Ответ 3

pd.concat, похоже, также не хватает памяти для больших фреймов данных, один из них - преобразование dfs в матрицы и объединение их.

def concat_df_by_np(df1,df2):
    """
    accepts two dataframes, converts each to a matrix, concats them horizontally and
    uses the index of the first dataframe. This is not a concat by index but simply by
    position, therefore the index of both dataframes should be the same
    """
    dfout = deepcopy(pd.DataFrame(np.concatenate( (df1.as_matrix(),df2.as_matrix()),axis=1),
                                  index   = df1.index, 
                                  columns = np.concatenate([df1.columns,df2.columns])))
    if (df1.index!=df2.index).any():
       #logging.warning('Indices in concat_df_by_np are not the same')                     
       print ('Indices in concat_df_by_np are not the same')                     


    return dfout

Однако нужно быть осторожным, поскольку эта функция не является объединением, а скорее горизонтальной добавляется, когда индексы игнорируются.