我目前正在将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
答案 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)