天天看点

c++ 读取内存数据 基址_【TOOLS】Pandas如何进行内存优化和数据加速读取(附代码详解)...

       Pandas 是常用的 Python 软件库,可用于数据操作和分析。在进行数据分析时,导入数据(例如pd.read_csv)几乎是必需的,但对于大的CSV,可能会需要占用大量的内存和读取时间,这对于数据分析时如果需要Reloading原始数据的话会非常低效。Dataquest.io 发布了一篇关于如何优化 pandas 内存占用的教程,仅需进行简单的数据类型转换,就能够将一个棒球比赛数据集的内存占用减少了近 90%,而pandas本身集成上的一些压缩数据类型可以帮助我们快速读取数据。 作者知乎:https://www.zhihu.com/people/bei-ke-er-1-34/activities

1. 内存优化

       一个现象是,在使用pandas进行数据处理的时候,加载大的数据或占用很大的内存和时间,甚至有时候发现文件在本地明明不大,但是用pandas以DataFrame形式加载内存中的时候会占用非常高的内存。        

       这里首先考虑python中的子类型(subtype)。pandas 内部将数值表示为 NumPy ndarrays,因为 pandas 表示同一类型的每个值时都使用同样的字节数,而 NumPy ndarray 可以存储值的数量,所以 pandas 可以快速准确地返回一个数值列所消耗的字节数。下表给出的各子类型所占的字节数。

c++ 读取内存数据 基址_【TOOLS】Pandas如何进行内存优化和数据加速读取(附代码详解)...

       关于数据存储,有这样一个比方,内存相当于仓库,数字相当于货物,数字需要装到箱子里才能堆到仓库。现在有小,中,大三种箱子,我们一个个数字用小箱子就可以装好,然后堆到仓库去,而现在pandas的处理逻辑是,如果你不告诉用哪个箱子,我都会用最大的箱子去装,这样仓库很快就满了。OK,这就是有时候DataFrame内存占用过高的原因。      

        所以这里有个简单的思路是:我依次去遍历数据的所有列,检查每一列的数值范围包含在哪个最近的子类区间。我们可以用np.iinfo()来获取子类的范围,例如:np.iinfo(np.int8).min为-128, np.iinfo(np.int8).max为127,也就是在数据不溢出的前提下,in8的数值范围是-128~127,由前面可以知道,如果一个数为int型,pandas读进来后就是int64的类型,也就是占8 bytes,如果这列数最大为100,最小为1,那么用int64去存储他显然浪费了内存,所以我们可以astype他的类型为in8,这样相当于对内存进行了一个压缩优化,可以减小不少的内存,同等硬件条件下,处理数据变得更高效。       

        同样对float类型数据也做相同的处理。对于object型,下图对比展示了数值型数据怎样以Numpy数据类型存储,和字符串怎样以Python内置类型进行存储的:

c++ 读取内存数据 基址_【TOOLS】Pandas如何进行内存优化和数据加速读取(附代码详解)...

       和数值类数据不同, object 类型的内存使用是可变的。尽管每个指针仅占用 1 字节的内存,但如果每个字符串在 Python 中都是单独存储的,那就会占用实际字符串那么大的空间。       

       解决的办法是:pandas 在 0.15 版引入了 Categorials。category 类型在底层使用了int值来表示一个列中的值,而不是使用原始值。pandas 使用一个单独的映射词典将这些int值映射到原始值。只要当一个列包含有限的值的集合时,这种方法就很有用。当我们将一列转换成 category dtype 时,pandas 就使用最节省空间的 int 子类型来表示该列中的所有不同值。所以我们可以将object型数据astype成category 类型以优化存储空间。

2. 采用压缩格式存储

       通常,在构建复杂数据模型时,可以方便地对数据进行一些预处理。例如,如果您有10年的分钟频率耗电量数据,即使你指定格式参数,只需将日期和时间转换为日期时间可能需要20分钟。你真的只想做一次,而不是每次运行你的模型,进行测试或分析。你可以在此处执行的一项非常有用的操作是预处理,然后将数据存储在已处理的表单中,以便在需要时使用。但是,如何以正确的格式存储数据而无需再次重新处理?如果你要另存为CSV,则只会丢失datetimes对象,并且在再次访问时必须重新处理它。       

        Pandas本身有内置的解决方案,例如 HDF5和feather format , HDF5是一种专门用于存储表格数据阵列的高性能存储格式。Pandas的 HDFStore 类允许你将DataFrame存储在HDF5文件中,以便可以有效地访问它,同时仍保留列类型和其他元数据。它是一个类似字典的类,因此您可以像读取Python dict对象一样进行读写。而feather format也是内置的一个压缩格式,在读取的时候会获得更快的加速。

3. 优化效果展示

       这里我将这种优化方法写成一个类,并分别提供数据的压缩优化以及读取加速的API,以方便去使用他:GitHub[1]

c++ 读取内存数据 基址_【TOOLS】Pandas如何进行内存优化和数据加速读取(附代码详解)...

      可以看出,原CSV文件占用内存为616.95MB,优化内存后的占用仅为173.9MB,且相对于原来pd.read_csv的7.7s的loading time,读入优化后的预处理数据文件能很大程度上的加速了读取。

Reference

[1].https://www.kaggle.com/arjanso/reducing-dataframe-memory-size-by-65 

[2].https://zhuanlan.zhihu.com/p/56541628 

[3].https://blog.csdn.net/weiyongle1996/article/details/78498603

 GitHub:

[1]

 GitHub: https://github.com/lixiangwang/optimization-of-pandas-for-large-CSV

推荐原创干货阅读:  【Deep Learning】为什么卷积神经网络中的“卷积”不是卷积运算?【手把手AI项目】一、安装win10+linux-Ubuntu16.04的双系统(全网最详细) 聊聊近状, 唠十块钱的【Deep Learning】详细解读LSTM与GRU单元的各个公式和区别【TOOLS】在云服务器上托管执行自己的python3工程程序 公众号:AI蜗牛车 保持谦逊、保持自律、保持进步

c++ 读取内存数据 基址_【TOOLS】Pandas如何进行内存优化和数据加速读取(附代码详解)...

点个在看,么么哒!

c++ 读取内存数据 基址_【TOOLS】Pandas如何进行内存优化和数据加速读取(附代码详解)...

继续阅读