我一直在想......如果我正在将一个 400MB 的 csv 文件读入 pandas 数据帧(使用 read_csv 或 read_table),有没有办法猜测这需要多少内存?只是想更好地了解数据帧和内存......
7 回答
df.memory_usage()
将返回每列占用的字节数:
>>> 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
此外,传递deep=True
将启用更准确的内存使用报告,该报告说明了所包含对象的全部使用情况。
这是因为内存使用不包括不是数组 if 组件的元素消耗的内存deep=False
(默认情况)。
这是不同方法的比较 -sys.getsizeof(df)
最简单。
对于此示例,df
是一个具有 814 行、11 列(2 个整数、9 个对象)的数据帧 - 从 427kb 形状文件中读取
sys.getsizeof(df)
>>> 导入系统 >>> sys.getsizeof(df) (以字节为单位给出结果) 462456
df.memory_usage()
>>> df.memory_usage() ... (以 8 字节/行列出每列) >>> df.memory_usage().sum() 71712 (大约行 * cols * 8 个字节) >>> df.memory_usage(深=真) (列出每列的完整内存使用情况) >>> df.memory_usage(deep=True).sum() (以字节为单位给出结果) 462432
df.info()
将数据帧信息打印到标准输出。从技术上讲,这些是千字节(KiB),而不是千字节 - 正如文档字符串所说,“内存使用以人类可读的单位(base-2 表示)显示。” 所以要获取字节数将乘以 1024,例如 451.6 KiB = 462,438 字节。
>>> df.info() ... 内存使用量:70.0+ KB >>> df.info(memory_usage='deep') ... 内存使用量:451.6 KB
我想我会为讨论带来更多数据。
我对这个问题进行了一系列测试。
通过使用 pythonresource
包,我得到了我的进程的内存使用情况。
通过将 csv 写入StringIO
缓冲区,我可以轻松地测量它的大小(以字节为单位)。
我进行了两个实验,每个实验都创建了 20 个数据帧,这些数据帧的大小在 10,000 行到 1,000,000 行之间不断增加。两者都有 10 列。
在第一个实验中,我只在数据集中使用了浮点数。
这就是与 csv 文件相比,内存随着行数的增加而增加的方式。(大小以兆字节为单位)
第二个实验我采用了相同的方法,但数据集中的数据仅包含短字符串。
似乎 csv 的大小和数据帧的大小之间的关系可以变化很大,但是内存中的大小总是会大 2-3 倍(对于本实验中的帧大小)
我很想通过更多的实验来完成这个答案,如果你想让我尝试一些特别的东西,请发表评论。
你必须反过来做。
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
数据是随机的,所以压缩没有太大帮助
如果您知道dtype
数组的 s,那么您可以直接计算存储数据所需的字节数 + 一些用于 Python 对象本身的字节数。numpy
数组的一个有用属性是nbytes
. DataFrame
您可以通过执行从熊猫中的数组中获取字节数
nbytes = sum(block.values.nbytes for block in df.blocks.values())
object
dtype 数组每个对象存储 8 个字节(对象 dtype 数组存储指向 opaque 的指针PyObject
),因此如果您的 csv 中有字符串,则需要考虑read_csv
将这些字符串转换为object
dtype 数组并相应地调整您的计算。
编辑:
有关. numpy
_ _ object
dtype
由于只存储了一个引用,因此您还需要考虑数组中对象的大小。正如该页面所说,对象数组有点类似于 Pythonlist
对象。
就在这里。Pandas 会将您的数据存储在二维 numpyndarray
结构中,并按 dtype 对它们进行分组。ndarray
基本上是一个带有小标题的原始 C 数据数组。dtype
所以你可以通过将它包含的大小乘以数组的维度来估计它的大小。
例如:如果您有 1000 行 2列np.int32
和 5np.float64
列,您的 DataFrame 将有一个np.int32
2x1000 数组和一个 5x1000np.float64
数组,即:
4字节*2*1000 + 8字节*5*1000 = 48000字节
我相信这给了python中任何对象的内存大小。需要检查 pandas 和 numpy 的内部结构
>>> import sys
#assuming the dataframe to be df
>>> sys.getsizeof(df)
59542497