pandas DataFrame布尔切片内存异常及视图拷贝机制问题咨询
pandas 布尔索引内存开销与视图/拷贝机制说明
布尔切片未返回视图的原因与内存现象解释
你观测到的所有内存变化都符合 pandas 0.23.x 版本的底层实现逻辑:
- 布尔索引、花式索引(传入列表/数组作为筛选条件)默认不会返回视图,一定会生成数据拷贝,这是核心规则。pandas 仅对连续范围的位置切片(如
df.iloc[100:200, 3:5]这类步长为1的整数冒号切片)才会返回共享底层存储的视图,其他筛选方式均会独立复制数据。 - 筛选一半数据内存上涨50%:原数据集大小10GB,筛选出的5GB数据被完整拷贝到新的
dfsub对象中,总内存占用就是10GB原数据+5GB新拷贝=15GB,和观测结果完全一致。 - 少量筛选内存回落至10GB:当你仅筛选极少量行时,新
dfsub的拷贝占用可以忽略,同时上一个占5GB的dfsub对象因为没有引用被Python GC回收,总内存就会回到接近原数据集的10GB水平。 - 首次调用的瞬态内存翻倍:这是 pandas 0.23.x 版本的已知实现缺陷,首次执行布尔索引时,底层numpy处理布尔掩码会临时生成完整大小的原数组副本作为中间变量,筛选完成后才会裁剪为目标大小并释放临时数组,因此会出现瞬时10GB额外内存占用,总内存到20GB;后续调用时内部会复用掩码计算的缓存逻辑,不会再生成完整临时数组,因此没有瞬态峰值。
pandas 视图与拷贝的实际运行机制
pandas 底层基于 numpy 数组存储数据,视图的本质是多个DataFrame/Series对象共享同一块numpy数组内存,仅通过偏移量、步长参数区分访问范围,本身几乎无内存开销。
可以生成视图的严格条件
只有同时满足以下所有条件才会返回视图:
- 筛选方式为连续范围的位置切片,即仅使用
iloc传入步长为1的整数冒号切片,不能使用布尔数组、列表、标签作为筛选条件 - 筛选的列属于同一dtype存储块:pandas会把相同数据类型的列合并存储在同一个numpy数组中,如果筛选的列属于不同dtype的存储块,会触发跨块数据拷贝
- 原数据集的底层numpy数组是连续存储的,没有被之前的重排、筛选操作打乱存储顺序
必然生成拷贝的场景
只要符合以下任意一种情况就会生成独立数据拷贝:
- 使用布尔索引、花式索引(列表/数组作为筛选参数)
- 使用
loc做标签索引且筛选范围非连续 - 筛选的列属于不同dtype的存储块
- 对子对象执行修改操作,触发写时拷贝(你使用的0.23.4版本写时拷贝机制不完善,很多无修改场景也会触发不必要的拷贝,pandas 2.0+版本优化了写时拷贝逻辑,可大幅减少不必要的内存开销)
内容的提问来源于stack exchange,提问作者Kevin S.
相关产品推荐
相关产品推荐

