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

use*_*739 7 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'])
Run Code Online (Sandbox Code Playgroud)

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

def do_nothing(group):
    return group
Run Code Online (Sandbox Code Playgroud)

并运行以下命令:

df = df.groupby('a').apply(do_nothing)
Run Code Online (Sandbox Code Playgroud)

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

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

干杯,

.P

Jef*_*eff 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
Run Code Online (Sandbox Code Playgroud)

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

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

代替:

df.groupby(...).apply(lambda x: x.sum() / x.mean())
Run Code Online (Sandbox Code Playgroud)

做得更好:

g = df.groupby(...)
g.sum() / g.mean()
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)