Подтвердить что ты не робот

Pandas Освобождение памяти GroupBy

Проблема

Я заметил, что память, выделенная при повторении через объект Pandas GroupBy, не освобождается после итерации. Я использую resource.getrusage(resource.RUSAGE_SELF).ru_maxrss (второй ответ в этом сообщении для подробностей), чтобы измерить общий объем активной памяти, используемой процессом Python.

import resource
import gc

import pandas as pd
import numpy as np

i = np.random.choice(list(range(100)), 4000)
cols = list(range(int(2e4)))

df = pd.DataFrame(1, index=i, columns=cols)

gb = df.groupby(level=0)
# gb = list(gb)
for i in range(3):
    print(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1e6)
    for idx, x in enumerate(gb):
        if idx == 0:
            print(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1e6)
    # del idx, x
    # gc.collect()

печатает следующую общую активную память (в gb)

0.671732
1.297424
1.297952
1.923288
1.923288
2.548624

Решение

Раскомментирование del idx, x и gc.collect() устраняет проблему. Тем не менее у меня есть del все переменные, которые ссылаются на DataFrames, возвращаемые путем итерации по группе (что может быть болью в зависимости от кода во внутреннем цикле). Новые способы использования печатной памяти:

0.671768
1.297412
1.297992
1.297992
1.297992
1.297992

В качестве альтернативы я могу раскомментировать gb = list(gb). Полученные в результате операции памяти примерно такие же, как в предыдущем решении:

1.32874
1.32874
1.32874
1.32874
1.32874
1.32874

Вопросы

  • Почему память для DataFrames, полученная в результате итерации через группу, не освобождается после завершения итерации?
  • Есть ли лучшее решение, чем два выше? Если нет, то какое из этих двух решений "лучше"?
4b9b3361

Ответ 1

Weirdness памяти

Это очень интересно! Вам не нужно del idx, x. Только использование gc.collect() работало, чтобы сохранить постоянную память для меня. Это намного чище, чем с операторами del внутри цикла.

Ответ 2

Почему память для DataFrames, полученная в результате итерации через группу, не освобождается после завершения итерации?

Нигде в вашем коде вы del object gb, а это значит, что в конце все еще есть. Одна вещь состоит в том, чтобы итератор дошел до конца своего цикла, тогда я ожидал бы, что он умрет автоматически, но объект, который вызвал итератор, сохраняется, если вам нужно сделать что-то еще (повторить снова, заполнить и т.д.),.