如何估算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文件相比,这是内存如何作为行数的函数增加的。 (以兆字节为单位)
第二个实验我有相同的方法,但数据集中的数据只包含短string。
似乎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