Pandas列选择性能差异:多列列表选择为何大幅变慢?
Pandas列选择性能差异的深层原因
咱们先明确测试场景:用1000万行×10列的大DataFrame做对比,测试代码如下:
import pandas as pd import numpy as np df = pd.DataFrame(np.random.randn(10**7,10), columns=list('abcdefghij'))
下面针对你观察到的性能差异逐一拆解原因:
1. 单列选择的高效性:轻量Series的优势
不管用df['b']、df.iloc[:,1]还是df.loc[:,'b'],最终返回的都是Series对象——这是性能飞快的核心:
- Series是纯一维结构,只需要维护一组数据和一个索引,没有DataFrame那样的列索引管理、多列对齐逻辑等额外开销。
- 像
df['b']这种直接列名索引,Pandas内部能直接通过列名映射找到对应的内存块,几乎是O(1)的查找,返回的甚至可能是原数据的视图(无需深拷贝),所以速度快到离谱(3.17µs)。 iloc/loc单列选择稍慢一点,是因为它们要处理更通用的索引校验(比如标签定位、边界检查),但本质还是返回轻量的Series,性能依然碾压多列选择。
2. 多列列表选择的性能瓶颈:DataFrame的重组开销
当你用df[['b','c']]、df.loc[:,['b','c']]或df.iloc[:,[1,2]]时,返回的是全新的DataFrame,这里的性能损耗主要来自三点:
- 数据重组与拷贝:哪怕你选的是连续列,用列表索引也会触发“逐列提取+重新组装”的逻辑——Pandas没法直接引用原数据的连续内存块,必须把每列数据单独拎出来,再分配新内存、拷贝数据、拼成新DataFrame,这个过程对1000万行的大表来说开销巨大。
- 对象初始化额外开销:创建新DataFrame需要初始化列索引、数据容器、对齐规则等,这些操作的耗时会被大表数据量放大。
- 索引校验逻辑:
loc/iloc处理列表索引时,要逐一检查每个索引的有效性,确保没有越界或不存在的列,这也会增加额外计算时间。
3. iloc切片选择的高效性:连续内存的直接利用
而df.iloc[:,1:3]这种切片选择之所以快,核心是它选中的是连续列:
- Pandas能直接识别这是一块连续的内存区域,不需要逐列提取重组,而是可以直接创建原数据的视图(或高效浅拷贝),只需要调整DataFrame的列索引范围就行,数据本身不需要大规模拷贝。
- 切片的校验逻辑也更简单:只需要确认起始和结束位置的有效性,不用遍历列表里的每个元素,所以性能和单列选择(iloc方式)处于同一量级(103µs vs 66.7µs)。
补充:Series vs DataFrame的性能差异
你提到的Series比DataFrame处理快,本质就是结构复杂度的差异:
- Series是纯一维结构,所有操作都是针对单一数组的,没有多列之间的协调、对齐等额外逻辑。
- DataFrame相当于多个Series的集合,要维护列索引、处理多列数据的对齐、广播等,哪怕只有两列,内部管理开销也比单个Series大得多——这就是相同数据量下,DataFrame操作更慢的原因。
总结
- 单列选择返回轻量Series,高效无压力;
- 多列列表选择需要重组数据生成DataFrame,开销暴增;
- 连续列切片能利用连续内存,性能接近单列水平。
内容的提问来源于stack exchange,提问作者Daniel R
相关产品推荐
相关产品推荐

