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