Pandas大数据集下基于双条件高效创建新列的优化方案
Pandas大数据集下基于双条件高效创建新列的优化方案
我太懂这种痛点了!用apply逐行处理大数据集的时候,速度慢得让人忍不住吐槽——毕竟apply本质上就是披着Pandas外衣的Python循环,完全没用到Pandas底层的向量化优势。咱们直接把你的代码重构一下,让处理速度直接起飞!
问题核心分析
你的需求很明确:
- 当
hour列不等于235999时,把整数格式的date转成标准日期 - 当
hour等于235999时,转成日期后再加1个工作日
原代码的问题在于逐行调用pd.to_datetime和判断条件,这在小数据集上没问题,但数据量上去后,Python级别的循环会拖慢整个流程。
优化方案:用向量化操作替代逐行循环
我们可以把所有操作都改成Pandas原生的向量化方法,底层是C实现的,速度能提升几个数量级:
import pandas as pd import numpy as np import time df = pd.DataFrame(data={'date': [20150101, 20150102, 20150103, 20150104, 20150105], 'hour': [113000, 142500,170000,235999,81500]}) start_time = time.time() # 第一步:一次性把整个date列转成datetime(向量化操作,比逐行快N倍) base_date = pd.to_datetime(df['date'], format='%Y%m%d') # 第二步:创建布尔掩码,标记需要加工作日的行 mask = df['hour'] == 235999 # 第三步:初始化new_date,再对符合条件的行批量加工作日 df['new_date'] = base_date.copy() df.loc[mask, 'new_date'] += pd.offsets.BDay(1) print(round(time.time() - start_time,2), 'Seconds')
更简洁的写法(用numpy.where)
如果你喜欢一行搞定,也可以用np.where,同样是向量化操作:
df['new_date'] = np.where( df['hour'] != 235999, pd.to_datetime(df['date'], format='%Y%m%d'), pd.to_datetime(df['date'], format='%Y%m%d') + pd.offsets.BDay(1) )
为什么这个方案更快?
- 所有操作都是向量化批量处理,没有逐行遍历的开销
pd.to_datetime只需要调用一次,而不是每一行都调用一次df.loc[mask]的赋值操作是底层批量修改,远快于逐行赋值
你可以试试用10万+行的数据集测试,原代码可能需要几十秒,优化后的代码只需要几百毫秒!
备注:内容来源于stack exchange,提问作者Zryan
相关产品推荐
相关产品推荐

