如何估算Pandas的DataFrame需要多less内存?

我一直在想…如果我正在阅读一个400MB的csv文件到一个pandas数据框(使用read_csv或read_table),有什么办法来猜测这将需要多less内存? 试图获得更好的dataframe和内存的感觉…

df.memory_usage()将返回每列占用多less:

 >>> df.memory_usage() Row_ID 20906600 Household_ID 20906600 Vehicle 20906600 Calendar_Year 20906600 Model_Year 20906600 ... 

要包含索引,请传递index=True

所以要获得整体内存消耗:

 >>> df.memory_usage(index=True).sum() 731731000 

你必须做相反的事情。

 In [4]: DataFrame(randn(1000000,20)).to_csv('test.csv') In [5]: !ls -ltr test.csv -rw-rw-r-- 1 users 399508276 Aug 6 16:55 test.csv 

从技术上说,内存就是这个(包括索引)

 In [16]: df.values.nbytes + df.index.nbytes + df.columns.nbytes Out[16]: 168000160 

因此,内存为168MB,400MB文件,1M行20浮点列

 DataFrame(randn(1000000,20)).to_hdf('test.h5','df') !ls -ltr test.h5 -rw-rw-r-- 1 users 168073944 Aug 6 16:57 test.h5 

编写为二进制HDF5文件时更加紧凑

 In [12]: DataFrame(randn(1000000,20)).to_hdf('test.h5','df',complevel=9,complib='blosc') In [13]: !ls -ltr test.h5 -rw-rw-r-- 1 users 154727012 Aug 6 16:58 test.h5 

数据是随机的,所以压缩不会有太大的帮助

我想我会带来更多的数据来讨论。

我在这个问题上进行了一系列testing。

通过使用python resource包,我得到了我的进程的内存使用情况。

通过将csv写入一个StringIO缓冲区,我可以很容易地测量它的大小,以字节为单位。

我进行了两个实验,每个实验创build了10,000行和1,000,000行之间增加大小的20个dataframe。 都有10列。

在第一个实验中,我只在我的数据集中使用了浮点数。

与csv文件相比,这是内存如何作为行数的函数增加的。 (以兆字节为单位)

内存和CSV大小(以兆字节为单位)作为具有浮点条目的行数的函数

第二个实验我有相同的方法,但数据集中的数据只包含短string。

内存和CSV大小,以兆字节为单位,具有字符串条目的行数

似乎csv的大小和dataframe的大小之间的关系可能会有很大的变化,但是内存中的大小总是会增大2-3倍(对于本实验中的帧大小)

我很想用更多的实验来完成这个答案,如果你想让我尝试一些特别的东西,请发表评论。

如果你知道你的数组的dtype ,那么你可以直接计算它将用来存储你的数据的字节数+对于Python对象本身。 numpy数组的有用属性是nbytes 。 您可以通过做一个pandas DataFrame的数组来获取字节数

 nbytes = sum(block.values.nbytes for block in df.blocks.values()) 

object dtype数组每个对象存储8个字节(对象dtype数组存储一个指向不透明PyObject的指针),所以如果你在csv中有string,你需要考虑到read_csv会把它们转换成object dtype数组并相应地调整你的计算。

编辑:

有关object dtype更多详细信息,请参见numpy标量types页面 。 由于只存储引用,所以还需要考虑数组中对象的大小。 正如该页所述,对象数组有点类似于Python list对象。

就在这里。 pandas将存储您的数据在二维numpy ndarray结构分组他们由dtypes。 ndarray基本上是一个具有ndarray的原始C数据。 所以你可以通过将它所包含的dtype以数组的维数来估计它的大小。

例如:如果您有1000行,包含2个np.int32和5个np.float64列,那么您的DataFrame将有一个np.int32数组和一个5×1000 np.float64数组,它是:

4字节* 2 * 1000 + 8字节* 5 * 1000 = 48000字节

这我相信这给了内存大小python中的任何对象。 内部需要检查pandas和numpy

 >>> import sys #assuming the dataframe to be df >>> sys.getsizeof(df) 59542497