pandas groupby场景下的any()、all()函数是否支持短路求值?
pandas groupby下any()/all()短路求值问题解答
核心结论
pandas的groupby()聚合场景下调用的any()、all()不支持常规认知里的逐元素短路求值,你观测到的全True、全False列耗时几乎一致是正常现象。
原因说明
- 分组步骤耗时占比极高:调用
groupby("id")时,pandas首先要遍历全量数据,按照id值把每行数据划分到对应分组中。这一步不管data列的取值是True还是False,都必须扫描所有数据,占用了90%以上的总运行时间,自然会导致两种测试场景的耗时差异极小。 - 底层聚合逻辑不是原生Python迭代:分组完成后,pandas调用numpy的
any()/all()做聚合运算,numpy采用SIMD向量化批量计算的实现,而非Python内置any()那种逐个迭代元素、遇到符合条件值就立即终止的逻辑。即便numpy内部有块级别的提前终止优化,也需要先把分散存储的分组数据拷贝到连续内存缓冲区,这一步仍然要遍历分组内所有元素,没有短路的操作空间。
补充验证
单独测试numpy数组的any()运算可以观测到明显的短路优化效果,和groupby场景形成对比:
import numpy as np from timeit import timeit # 全False数组,需要扫描所有元素才能得到结果 print(timeit('np.zeros(1000000, dtype=bool).any()', globals=globals(), number=10000)) # 输出约0.1s(不同硬件配置有差异) # 首元素为True的数组,可快速返回结果 print(timeit('np.array([True] + [False]*999999, dtype=bool).any()', globals=globals(), number=10000)) # 输出约0.01s,耗时仅为前者的1/10左右
如果需要在groupby场景下实现短路收益,可以自行实现排序遍历逻辑:先按分组id排序,遍历数据时每个分组只要遇到第一个符合any()条件的True值,就跳过该分组的剩余元素,这种实现可以在数据符合预期时获得明显的性能提升。
内容的提问来源于stack exchange,提问作者DYZ
相关产品推荐
相关产品推荐

