Pandas GroupBy内存释放

19

问题

我注意到,在迭代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, xgc.collect()可以解决问题。但是,我必须del所有引用通过对groupby进行迭代返回的DataFrames的变量(这取决于内部for循环中的代码,可能会很麻烦)。新的打印内存使用情况如下:

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

问题

  1. 为什么通过对groupby进行迭代后生成的DataFrame内存没有在迭代完成后被释放?
  2. 除了上述两种解决方案,是否有更好的解决方案?如果没有,这两种解决方案中哪一种更好?

你正在使用Python2还是3? - Padraic Cunningham
很奇怪,每次迭代都会创建新的对象,但是似乎还保留了某个引用,所以仅调用gc.collect并不足够。使用列表方法可以重复使用相同的对象,因此您不会看到内存增加。 - Padraic Cunningham
2个回答

1

内存异常

这非常有趣!您不需要使用del idx, x。仅使用gc.collect()就可以使我的内存保持恒定。这比在循环内部使用del语句更加简洁。


我得到的结果不同。如果我不del引用x,那么内存会增加两倍(~0.67gb -> ~1.3gb -> 2gb)。 - Alex
嗯...我在iPython中运行了这个,不需要使用del...你在哪里运行它? - tmthydvnprt
你是指Pandas的哪个版本?0.18.0。 - Alex
3
什么环境?是在 iPython 内部吗?是命令行界面吗?还是其他完整应用程序的一部分? - tmthydvnprt

0
为什么通过对groupby进行迭代得到的DataFrames内存在迭代完成后没有被释放?
你的代码中没有删除对象gb,这意味着它在最后仍然存在。一个迭代器到达其循环的末尾时会自动消失,但是产生迭代器的对象仍然存在,以防需要执行其他操作(再次迭代、聚合等)。

o.o 你在说什么? - AsheKetchum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接