[英]Memory leak when reading value from a Pandas Dataframe
当从数据帧中迭代复制一个值时,pandas 似乎会触发内存泄漏。
在每次迭代开始时,通过从初始数据帧复制来创建数据帧。 通过从当前数据帧复制单个值来创建第二个变量。
在每次迭代结束时,删除这两个变量,并打印当前进程使用的内存(每 1000 次迭代)。 使用的内存增加了!
我认为在某些时候可能会有一些隐式副本(可能是在读取数据帧值时)。
对此问题的快速修复导致在每次迭代时应用垃圾收集器,但这是一个相当昂贵的解决方案:该过程至少慢 10 倍。
是否有明确的解释为什么会出现这个问题?
import os, gc
import psutil, pandas as pd
N_ITER = 100000
DF_SIZE = 10000
# Define the DataFrame
df = pd.DataFrame(index=range(DF_SIZE), columns=['my_col'])
df['my_col'] = range(DF_SIZE)
def memory_usage():
"""Return the memory usage of the current python process."""
return psutil.Process(os.getpid()).memory_info().rss / 1024 ** 2
if __name__ == '__main__':
for i in range(N_ITER):
df_ind = pd.DataFrame(df.copy())
val = df_ind.at[4242, 'my_col'] # The line that provokes the leak!
del df_ind, val # Useless
# gc.collect() # Garbage Collector prevents the leak but is slow
if (i % 1000) == 0:
print('Iter {}\t {} MB'.format(i, int(memory_usage())))
好吧,看来真正的痛苦来自于df_ind
的创建方式。
使用引用到原来的数据帧df
似乎工作,但如果我们打算修改可能是有点太冒险了df_ind
。
使用原始数据帧df
副本会触发内存泄漏。 df
可能有一些无用元素的隐式副本。 这些复制的元素不会被del
捕获,而是被gc.collect()
捕获。 这会带来时间成本,因为此操作需要时间。
以下列出了解决此内存泄漏的不同尝试及其结果:
df_ind = df # Works! Dangerous since df could be modified
df_ind = copy.copy(df) # Works! Equivalent to df_ind = df
df_ind = df.copy.deepcopy(df) # Fails.
df_ind = df.copy(deep=False) # Works! Equivalent to df_ind = df
df_ind = df.copy(deep=True) # Fails.
总结:
如果要修改临时数据框,请不要使用 pandas 。 您可以使用字典或压缩列表来获取您想要的内容。
如果您不想修改临时数据帧,则使用带有显式选项df_ind = df.copy(deep=False)
熊猫
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.