如何加速Pandas DataFrame中所有行对的嵌套循环?
问题描述
我有一个约8万行的DataFrame,格式如下:
df = pd.DataFrame({'Year': [1900, 1902, 1903], 'Name': ['Tom', 'Dick', 'Harry']}) Year Name 0 1900 Tom 1 1902 Dick 2 1903 Harry
我需要以Name列的每一组组合(含自身与自身的组合)作为参数调用函数,当前使用以下代码实现(用print替代函数调用):
for i, n1 in enumerate(df.itertuples()): for n2 in df[i:].itertuples(): print(n1.Name, n2.Name)
请问是否有我忽略的加速方法?另外,我需要跟踪每个名称对的索引,若使用itertools.combinations处理索引,仍需执行代价较高的df.loc调用。
解决方案
一、核心加速思路
你的代码核心问题是Python级嵌套循环效率极低,加上反复从DataFrame读取数据的额外开销,导致整体速度缓慢。可以通过以下两点大幅优化:
1. 提前提取Name列的numpy数组
将Name列转为numpy数组,直接通过索引访问元素的速度比df.loc或itertuples的对象属性访问快一个数量级:
names = df['Name'].values
2. 用itertools生成组合替代嵌套循环
itertools模块的组合生成逻辑是C语言实现的,远快于Python原生循环。结合你的需求(包含自身与自身的组合),使用combinations_with_replacement生成索引对,再通过提前提取的numpy数组获取名称,完全规避df.loc的高代价调用:
import itertools # 生成所有满足 j >= i 的索引对 for idx1, idx2 in itertools.combinations_with_replacement(df.index, 2): name1 = names[idx1] name2 = names[idx2] # 替换为你的函数调用,例如 func(name1, name2) print(name1, name2)
若你需要的是不含自身与自身的严格无序对(j > i),则改用itertools.combinations(df.index, 2)即可。
二、优化效果的核心原因
- 消除Python循环开销:
itertools的组合生成在底层执行,避免了Python级循环的性能损耗。 - 简化数据访问路径:numpy数组的索引访问是直接内存操作,比DataFrame的属性/索引访问少了大量封装层的开销。
- 低内存占用:
itertools采用惰性生成逻辑,不会一次性生成所有组合(8万行的组合数约3.2亿,直接生成会耗尽内存),仅按需生成每组数据。
三、额外优化建议
如果你的函数支持批量处理,可以尝试用广播生成组合数组,但需注意8万行的组合规模会占用极大内存,迭代处理仍是更稳妥的选择。
内容的提问来源于stack exchange,提问作者primelens
相关产品推荐
相关产品推荐

