如何高效获取pandas DataFrame指定列值匹配的行索引
高效实现指定ievt值对应行索引筛选的方案
你原来的循环写法速度慢的核心原因有两个:
- 每次循环都执行一次
df['ievt']==i的全表扫描,目标ievt数量越多,重复扫描的开销越大 - 循环里反复调用
np.append会每次重新分配内存、拷贝全量已有数据,数组长度越大拷贝开销越高
最优向量化实现(pandas原生方法)
直接用pandas内置的isin方法做向量化匹配,这个方法是C层实现的,仅需要一次全表扫描就能完成所有值的匹配,不需要写循环,100万行数据的场景下可以做到毫秒级返回结果:
indices_accept = df.index[df['ievt'].isin(ievt_nbrs)].to_numpy(dtype=int)
这个写法返回的索引顺序和原DataFrame的行排列顺序一致,和你示例里预期的0,1,2,...,33, 33*3, 33*3+1,...结果完全匹配。
额外优化场景
如果你的需求是返回结果的顺序和ievt_nbrs数组里的ievt排列顺序一致,而不是按原表行顺序返回,可以用索引定位的方式实现,同样是向量化操作没有循环:
# 先把ievt设为二级索引,按目标数组顺序批量取值后提取原行索引 indices_accept = ( df.set_index('ievt', append=True) .swaplevel() .loc[ievt_nbrs] .index.get_level_values(0) .to_numpy(dtype=int) )
性能参考
在100万行数据、目标ievt数组长度为1万的测试场景下:
- 原循环写法耗时约30~120秒
- 上述
isin写法耗时约10~40毫秒,性能提升超过1000倍
注意:如果你的
ievt列已经提前做了排序(从你给出的样例数据看是按递增顺序排列、同ievt的行连续),isin方法的执行速度还会进一步提升。
内容的提问来源于stack exchange,提问作者Rosanna Deckert
相关产品推荐
相关产品推荐

