Python含if条件的逐行循环提速方法咨询(600万行数据集)
如何加速百万级数据集的NaN填充操作
嗨,这个问题我太有发言权了!处理600万行的数据集时,Python的普通逐行循环完全是性能灾难,更别说你代码里还加了print(i)——这个IO操作会把速度拖得更慢,先赶紧把它删掉!
先说说原代码的核心问题
- Pandas逐行操作天生低效:Pandas是基于向量化设计的,底层用C实现了批量操作优化,而你用
for循环逐行调用iloc,相当于绕过了所有优化,每一行都要做Python层面的逻辑判断和数据定位,600万行的话耗时会非常夸张。 - 重复索引定位开销:每次
iloc[i-1,3]都要重新定位行和列,这是额外的性能浪费。 - 不必要的IO拖慢:循环里的
print(i)会频繁输出到控制台,IO操作的速度比内存计算慢几个数量级,直接拖慢整个流程。
最优解决方案:用Pandas内置向量化函数(秒级处理)
你的需求是:当open price为NaN时,用上一行的close price填充。这个逻辑完全可以用Pandas的shift()和fillna()组合实现,全程向量化操作,底层C执行,600万行基本几秒就能搞定:
import pandas as pd # 1. 生成上一行的close price序列(向下偏移1行) prev_close = price3['close price'].shift(1) # 2. 用prev_close填充open price中的NaN值 price3['open price'] = price3['open price'].fillna(prev_close)
如果你的数据是按symbol分组的(不同股票/标的的价格不能互相填充),一定要加上分组操作,避免逻辑错误:
# 按symbol分组后,用组内上一行的close price填充当前行的open price NaN price3['open price'] = price3.groupby('symbol').apply( lambda group: group['open price'].fillna(group['close price'].shift(1)) ).reset_index(level=0, drop=True)
关于你问的apply()如何加条件(不推荐大数据量)
虽然apply()也能实现,但它本质还是逐行遍历,速度远不如向量化操作,600万行的话依然会很慢。不过满足你的疑问,这里给出实现方式:
# 先新增一列存储上一行的close price price3['prev_close'] = price3['close price'].shift(1) # 用apply逐行判断,填充NaN price3['open price'] = price3.apply( lambda row: row['prev_close'] if pd.isna(row['open price']) else row['open price'], axis=1 # axis=1表示逐行处理 ) # 用完可以删掉临时列 price3.drop('prev_close', axis=1, inplace=True)
同样,如果需要分组,也要在groupby后使用apply。
额外小贴士
- 永远优先选择Pandas的内置向量化函数(比如
fillna、shift、replace等),避免手动写循环。 - 如果一定要用循环(比如逻辑极其复杂),可以试试用
numba库给循环加速,或者转换成NumPy数组后再循环,速度会比直接操作DataFrame快很多。 - 调试时不要逐行打印,改用
print(f"Processed {i/1000000:.2f}M rows")每隔100万行打印一次,减少IO开销。
内容的提问来源于stack exchange,提问作者Ekaterina
相关产品推荐
相关产品推荐

