165

我一直在想......如果我正在将一个 400MB 的 csv 文件读入 pandas 数据帧(使用 read_csv 或 read_table),有没有办法猜测这需要多少内存?只是想更好地了解数据帧和内存......

4

7 回答 7

143

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(默认情况)。

于 2015-10-06T12:34:11.840 回答
108

这是不同方法的比较 -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
于 2017-12-11T11:06:42.300 回答
52

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

我对这个问题进行了一系列测试。

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

通过将 csv 写入StringIO缓冲区,我可以轻松地测量它的大小(以字节为单位)。

我进行了两个实验,每个实验都创建了 20 个数据帧,这些数据帧的大小在 10,000 行到 1,000,000 行之间不断增加。两者都有 10 列。

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

这就是与 csv 文件相比,内存随着行数的增加而增加的方式。(大小以兆字节为单位)

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

第二个实验我采用了相同的方法,但数据集中的数据仅包含短字符串。

内存和 CSV 大小(以兆字节为单位)与字符串条目的行数有关

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

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

于 2015-07-21T15:29:36.647 回答
32

你必须反过来做。

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

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

于 2013-08-06T21:00:08.960 回答
10

如果您知道dtype数组的 s,那么您可以直接计算存储数据所需的字节数 + 一些用于 Python 对象本身的字节数。numpy数组的一个有用属性是nbytes. DataFrame您可以通过执行从熊猫中的数组中获取字节数

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

objectdtype 数组每个对象存储 8 个字节(对象 dtype 数组存储指向 opaque 的指针PyObject),因此如果您的 csv 中有字符串,则需要考虑read_csv将这些字符串转换为objectdtype 数组并相应地调整您的计算。

编辑:

有关. numpy_ _ object dtype由于只存储了一个引用,因此您还需要考虑数组中对象的大小。正如该页面所说,对象数组有点类似于 Pythonlist对象。

于 2013-08-06T20:38:29.463 回答
10

就在这里。Pandas 会将您的数据存储在二维 numpyndarray结构中,并按 dtype 对它们进行分组。ndarray基本上是一个带有小标题的原始 C 数据数组。dtype所以你可以通过将它包含的大小乘以数组的维度来估计它的大小。

例如:如果您有 1000 行 2列np.int32和 5np.float64列,您的 DataFrame 将有一个np.int322x1000 数组和一个 5x1000np.float64数组,即:

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

于 2013-08-06T20:30:28.387 回答
8

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

>>> import sys
#assuming the dataframe to be df 
>>> sys.getsizeof(df) 
59542497
于 2016-11-14T09:18:09.970 回答