Pandas.groupby.apply()中的内存泄漏?

时间:2014-08-05 03:43:08

标签: python memory-leaks pandas

我目前正在将Pandas用于csv源文件大约600mb的项目。在分析过程中,我在csv中读取数据帧,对某些列进行分组并将一个简单函数应用于分组数据帧。我注意到我在这个过程中进入了Swap Memory,所以进行了一个基本的测试:

我首先在shell中创建了一个相当大的数据框:

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(3000000, 3),index=range(3000000),columns=['a', 'b', 'c'])

我定义了一个名为do_nothing()的无意义函数:

def do_nothing(group):
    return group

并运行以下命令:

df = df.groupby('a').apply(do_nothing)

我的系统有16GB的RAM并运行Debian(Mint)。创建数据帧后,我使用了~600mb的RAM。一旦apply方法开始执行,该值就开始飙升。它在完成命令之前稳步爬升到7gb左右(!)并且恢复到5.4gb(而shell仍处于活动状态)。问题是,我的工作需要做的不仅仅是做什么?在执行实际程序的同时,我限制了16GB的RAM并开始交换,使程序无法使用。这是有意的吗?我不明白为什么Pandas应该需要7gb的RAM来有效地“do_nothing”,即使它必须存储分组的对象。

有关导致此问题/如何解决问题的任何想法?

干杯,

.P

1 个答案:

答案 0 :(得分:11)

使用0.14.1,我不认为它们是内存泄漏(帧的1/3大小)。

In [79]: df = DataFrame(np.random.randn(100000,3))

In [77]: %memit -r 3 df.groupby(df.index).apply(lambda x: x)
maximum of 3: 1365.652344 MB per loop

In [78]: %memit -r 10 df.groupby(df.index).apply(lambda x: x)
maximum of 10: 1365.683594 MB per loop

关于如何处理这样的问题的两个一般性评论:

1)如果可能的话,使用cython level函数会更快,并且将使用更少的内存。 IOW,使用函数将groupby表达式与void分离几乎总是值得的(如果可能的话,某些事情太复杂了,但这就是重点,你想要破坏它)。 e.g。

而不是:

df.groupby(...).apply(lambda x: x.sum() / x.mean())

做得更好:

g = df.groupby(...)
g.sum() / g.mean()

2)您可以通过手动进行聚合来轻松“控制”群组(此外,如果需要,这将允许定期输出和垃圾收集)。

results = []
for i, (g, grp) in enumerate(df.groupby(....)):

    if i % 500 == 0:
        print "checkpoint: %s" % i
        gc.collect()


    results.append(func(g,grp))

# final result
pd.concate(results)