如何使用Pandas处理超过内存容量的大规模数据?

处理大规模数据集时常是棘手的事情 , 尤其在内存无法完全加载数据的情况下 。 在资源受限的情况下 , 可以使用 Python Pandas 提供的一些功能 , 降低加载数据集的内存占用 。 可用技术包括压缩、索引和数据分块 。
开展数据科学项目中的一个重要步骤 , 就是从 API 下载数据并加载到本地内存 , 之后才能处理数据 。
在上述过程中需要解决一些问题 , 其中之一就是数据量过大 。 如果数据量超出本机内存的容量 , 项目执行就会产生问题 。
对此有哪些解决方案?
有多种解决数据量过大问题的方法 。 它们或是消耗时间 , 或是需要增加投资 。
可能的解决方案

  1. 投资解决:新购有能力处理整个数据集 , 具有更强 CPU 和更大内存的计算机 。 或是去租用云服务或虚拟内存 , 创建处理工作负载的集群 。
  2. 耗时解决:如果内存不足以处理整个数据集 , 而硬盘的容量要远大于内存 , 此时可考虑使用硬盘存储数据 。 但使用硬盘管理数据会大大降低处理性能 , 即便是 SSD 也要比内存慢很多 。
只要资源允许 , 这两种解决方法均可行 。 如果项目资金充裕 , 或是不惜任何时间代价 , 那么上述两种方法是最简单也是最直接的解决方案 。
但如果情况并非如此呢?也许你的资金有限 , 或是数据集过大 , 从磁盘加载将增加 5~6 倍甚至更多的处理时间 。 是否有无需额外资金投入或时间开销的大数据解决方案呢?
这个问题正中我的下怀 。
有多种技术可用于大数据处理 , 它们无需额外付出投资 , 也不会耗费大量加载的时间 。 本文将介绍其中三种使用 Pandas 处理大规模数据集的技术 。
压缩第一种技术是数据压缩 。 压缩并非指将数据打包为 ZIP 文件 , 而是以压缩格式在内存中存储数据 。
换句话说 , 数据压缩就是一种使用更少内存表示数据的方法 。 数据压缩有两种类型 , 即无损压缩和有损压缩 。 这两种类型只影响数据的加载 , 不会影响到处理代码 。
无损压缩无损压缩不会对数据造成任何损失 , 即原始数据和压缩后的数据在语义上保持不变 。 执行无损压缩有三种方式 。 在下文中 , 将使用美国按州统计的新冠病毒病例数据集依次介绍 。
  • 加载特定的数据列
例子中所使用的数据集具有如下结构:
import pandas as pddata = http://kandian.youth.cn/index/pd.read_csv("")data.sample(10)
如何使用Pandas处理超过内存容量的大规模数据?文章插图
【如何使用Pandas处理超过内存容量的大规模数据?】加载整个数据集需要占用 111MB 内存!
如何使用Pandas处理超过内存容量的大规模数据?文章插图
如果我们只需要数据集中的两列 , 即州名和病例数 , 那么为什么要加载整个数据集呢?加载所需的两列数据只需 36MB , 可降低内存使用 32% 。
如何使用Pandas处理超过内存容量的大规模数据?文章插图
使用 Pandas 加载所需数据列的代码如下:
如何使用Pandas处理超过内存容量的大规模数据?文章插图
本节使用的代码片段如下:
#加载所需软件库 Import needed libraryimport pandas as pd#数据集csv = ""#加载整个数据集data = http://kandian.youth.cn/index/pd.read_csv(csv)data.info(verbose=False, memory_usage="deep")#创建数据子集df = data[["county", "cases"]]df.info(verbose=False, memory_usage="deep")#加速所需的两列数据df_2col = pd.read_csv(csv , usecols=["county", "cases"])df_2col.info(verbose=False, memory_usage="deep")代码地址: #file-column_selecting-py
  • 操作数据类型
另一个降低数据内存使用量的方法是截取数值项 。 例如将 CSV 加载到 DataFrame , 如果文件中包含数值 , 那么一个数值就需要 64 个字节存储 。 但可通过使用 int 格式截取数值以节省内存 。
  • int8 存储值的范围是 -128 到 127;
  • int16 存储值的范围是 -32768 到 32767;
  • int64 存储值的范围是 -9223372036854775808 到 9223372036854775807 。

如何使用Pandas处理超过内存容量的大规模数据?文章插图
如果可预先确定数值不大于 32767 , 那么就可以使用 int16 或 int32 类型 , 该列的内存占用能降低 75% 。
假定每个州的病例数不超过 32767(虽然现实中并非如此) , 那么就可截取该列为 int16 类型而非 int64 。
如何使用Pandas处理超过内存容量的大规模数据?文章插图