Pandas Dataframe内存问题

时间:2017-01-23 16:04:40

标签: python pandas

我在理解为什么Pandas Dataframes没有从内存中正确清除时遇到问题。我的机器达到16Gb的内存之后,我发现它应该保持在400 Mb左右。我创建一个DataFrame,然后在同一个函数内创建一个副本。多次评估此功能。每次评估函数时,内存都会增加 - 在下面的示例中为337 Mb:

import pandas as pd
import numpy as np
from memory_profiler import profile

@profile
def loop_df():
    for _ in xrange(100):
        copy_df()

# Create a df and then copy it
def copy_df():
    X = pd.DataFrame(np.random.rand(100000,10))
    X2 = X.loc[0:1000,:]
    return 

loop_df()

# Returns the following memory usage:

#Line #    Mem usage    Increment   Line Contents
#================================================
#    13    100.3 MiB      0.0 MiB   @profile
#    14                             def loop_df():
#    15    437.8 MiB    337.5 MiB       for _ in xrange(100):
#    16    437.8 MiB      0.0 MiB           copy_df()

有各种各样的线索涉及到这一点,但没有一个像样的解决方案:Memory leak using pandas dataframehttps://github.com/pandas-dev/pandas/issues/6046https://github.com/pandas-dev/pandas/issues/2659Pandas: where's the memory leak here?

对于可以采取哪些措施来避免这种情况的任何建议都是受欢迎的。到目前为止,使用垃圾收集器使用简单的示例,但在我的复杂代码中失败。使用多处理池也可以使用我复杂的代码。然而,拥有一个不必使用多处理模型的解决方案会很好。

任何人都可以解释为什么当Numpy数组和列表等Python对象不会导致这种行为时会发生这种情况?这是一个错误或DataFrame对象的预期行为?

1 个答案:

答案 0 :(得分:3)

使用del后跟gc.collect()似乎可以解决问题:

import pandas as pd
import numpy as np
import gc
from memory_profiler import profile

@profile
def loop_df():
    for _ in xrange(100):
        copy_df()

# Create a df and then copy it
@profile
def copy_df():
    X = pd.DataFrame(np.random.rand(100000,10))
    X2 = X.loc[0:1000,:]
    del X, X2
    gc.collect()

loop_df()

然后,如果你的内存不足,这里有一个使用numpy memmap(内存映射)数据结构的可能解决方案:

import pandas as pd
import numpy as np
from memory_profiler import profile
import gc

@profile
def loop_df():
    for _ in xrange(100):
        copy_df()
@profile
def copy_df():
    mmap = np.memmap('mymemmap', dtype='float64', mode='w+', shape=(100000,10))
    mmap[:] = np.random.rand(100000,10)
    df = pd.DataFrame(mmap)
    df2 = df.loc[0:1000,:]
    del df, df2, mmap
    gc.collect()
    pass

if __name__ == '__main__':
    loop_df()
  

内存映射文件用于访问磁盘上的大段文件,而无需将整个文件读入内存。

抱歉,我无法解释为什么您的示例代码不会释放pandas数据。我怀疑它与使用原生数组或其他东西的numpy和pandas有关。