如何提升DataFrame行级重索引(行扩展)的执行效率?
高效优化DataFrame行扩展操作的实用方案
嘿,我太懂这种感受了——明明逻辑简单到不行,但处理DataFrame行扩展时效率低到让人抓狂!之前帮不少人解决过类似的问题,给你分享几个亲测好用的高效方案,绝对比你现在用的循环/拼接快N倍!
方法1:固定次数批量扩展(用repeat)
如果你的需求是把每一行都重复固定的k次,真的别再写循环一行行拼接了,直接用Pandas自带的repeat()方法,完全是矢量化操作,底层都是优化过的C代码,速度拉满:
import pandas as pd import numpy as np # 构造和你示例类似的测试数据 myidx = pd.date_range('2016-01-01','2016-01-05') data = pd.DataFrame({'value': range(len(myidx))}, index=myidx) # 假设每一行要扩展成3行 expanded_data = data.loc[data.index.repeat(3)].reset_index(drop=False) # 给扩展后的行加个序号标识,方便区分 expanded_data['seq'] = expanded_data.groupby('index').cumcount() + 1 print(expanded_data.head(6))
输出结果:
index value seq 0 2016-01-01 0 1 1 2016-01-01 0 2 2 2016-01-01 0 3 3 2016-01-02 1 1 4 2016-01-02 1 2 5 2016-01-02 1 3
这种方法比循环append或者concat快几十倍,数据量越大,效率差距越明显。
方法2:根据列值动态扩展(用explode)
如果你的DataFrame里有一列指定了每行要扩展的次数,那可以先把次数转成对应长度的占位列表,再用explode()炸开实现行扩展:
# 给示例数据加一列,指定每行的扩展次数 data['expand_times'] = [2, 3, 1, 4, 2] # 把次数转成对应长度的占位列表 data['temp'] = data['expand_times'].apply(lambda x: [1]*x) # 炸开列表实现行扩展,最后清理临时列 expanded_data = data.explode('temp').drop(['expand_times', 'temp'], axis=1).reset_index(drop=False) expanded_data['seq'] = expanded_data.groupby('index').cumcount() + 1 print(expanded_data)
这种方法灵活度很高,能满足每行扩展次数不同的场景,而且explode()也是矢量化操作,效率远超纯Python循环。
方法3:生成连续序列的扩展(numpy组合操作)
如果你的需求是给每行生成一段连续的数值(比如从0到n-1),直接用numpy的tile和repeat组合操作,这是超大数据量下速度最快的方案:
# 假设每行要生成0到2的连续值 n = 3 # 用numpy构造扩展后的索引、value和序列值 new_index = np.tile(data.index, n) new_value = np.repeat(data['value'], n) seq = np.tile(np.arange(n), len(data)) # 组装成新的DataFrame expanded_data = pd.DataFrame({ 'index': new_index, 'value': new_value, 'seq': seq }) print(expanded_data.head(6))
这种方法完全绕开了Pandas的行级操作,直接用numpy的底层数组处理,在百万级以上数据量时优势特别显著。
关键提醒
一定要避免用Python循环逐行处理!Pandas和numpy的矢量化操作才是提升效率的核心,底层都是优化过的C代码,和纯Python循环的速度差能达到几个数量级。
内容的提问来源于stack exchange,提问作者ℕʘʘḆḽḘ
相关产品推荐
相关产品推荐

