У меня есть действительно большой файл csv, который я открыл в пандах следующим образом ....
import pandas
df = pandas.read_csv('large_txt_file.txt')
Как только я это сделаю, мое использование памяти увеличится на 2 ГБ, что и ожидается, поскольку этот файл содержит миллионы строк. Моя проблема возникает, когда мне нужно освободить эту память. Я сбежал ....
del df
Однако использование моей памяти не упало. Это неправильный подход к освобождению памяти, используемой фреймом данных pandas? Если да, то каков правильный способ?
gc
модуль и вызвать,gc.collect()
но он может не восстановить памятьdel df
не вызывается сразу после создания df, верно? Я думаю, что есть ссылки на df в момент удаления df. Таким образом, он не будет удален, вместо этого он удалит имя.df = ''
в конце вашего кода? Кажется, очищает RAM, используемую фреймом данных.Ответы:
Уменьшить использование памяти в Python сложно, потому что Python фактически не возвращает память операционной системе . Если вы удаляете объекты, память становится доступной для новых объектов Python, но не
free()
возвращается в систему ( см. Этот вопрос ).Если вы придерживаетесь числовых массивов numpy, они освобождаются, а упакованные объекты - нет.
Уменьшение количества фреймов данных
Python сохраняет нашу память на высоком уровне, но мы можем уменьшить общее количество создаваемых фреймов данных. При изменении фрейма данных предпочитайте
inplace=True
, чтобы вы не создавали копии.Еще одна распространенная проблема - сохранение копий ранее созданных фреймов данных в ipython:
Вы можете исправить это, набрав,
%reset Out
чтобы очистить историю. Кроме того, вы можете настроить, сколько истории хранится в ipythonipython --cache-size=5
(по умолчанию 1000).Уменьшение размера фрейма данных
По возможности избегайте использования типов объектов.
Значения с объектом dtype помещены в рамку, что означает, что массив numpy просто содержит указатель, и у вас есть полный объект Python в куче для каждого значения в вашем фрейме данных. Сюда входят струны.
Хотя numpy поддерживает строки фиксированного размера в массивах, pandas - нет ( это вызвало путаницу у пользователей ). Это может иметь большое значение:
Возможно, вы захотите избежать использования строковых столбцов или найти способ представления строковых данных в виде чисел.
Если у вас есть фрейм данных, который содержит много повторяющихся значений (NaN очень распространено), вы можете использовать разреженную структуру данных, чтобы уменьшить использование памяти:
Просмотр использования памяти
Вы можете просмотреть использование памяти ( документы ):
Начиная с pandas 0.17.1, вы также
df.info(memory_usage='deep')
можете видеть использование памяти, включая объекты.источник
Как отмечено в комментариях, есть несколько вещей, которые можно попробовать:
gc.collect
(@EdChum) может, например, очистить материал. По крайней мере, по моему опыту, эти вещи иногда работают, а часто - нет.Однако есть одна вещь, которая работает всегда, потому что это делается на уровне ОС, а не языка.
Предположим, у вас есть функция, которая создает промежуточный огромный DataFrame и возвращает меньший результат (который также может быть DataFrame):
Тогда, если вы сделаете что-то вроде
Затем функция выполняется в другом процессе . По завершении этого процесса ОС забирает все использованные ресурсы. На самом деле Python, pandas, сборщик мусора, ничего не могут сделать, чтобы остановить это.
источник
with multiprocessing.Pool(1) as pool: result = pool.map(huge_intermediate_calc, [something])
требует закрытия пула после завершения.Это решает для меня проблему освобождения памяти !!!
фрейм данных будет явно установлен на null
источник
del df
не будет удален, еслиdf
на момент удаления есть ссылка на . Поэтому вам нужно удалить все ссылки на него,del df
чтобы освободить память.Поэтому все экземпляры, привязанные к df, должны быть удалены, чтобы запустить сборку мусора.
Используйте objgragh, чтобы проверить, кто удерживает объекты.
источник
Кажется, есть проблема с glibc, которая влияет на выделение памяти в Pandas: https://github.com/pandas-dev/pandas/issues/2659
Обезьяна патч подробно по этому вопросу решил проблему для меня:
источник