Excel SUMIF转Python高效实现:寻求替代Pandas.apply的向量化条件求和方案
优化方案(向量化实现,时间复杂度O(n))
你原代码的逻辑是统计每行对应同ID、前1天的所有Stock值总和,可以用分组移位或者关联聚合两种向量化方式实现,完全避免逐行迭代:
方案1:同ID每天仅1条记录时使用(性能最高)
如果你的数据中同一个ID同一天只有1行记录,直接用groupby + shift即可:
import pandas as pd # 读取数据 data = pd.read_excel(settings['input_file'], sheet_name = "Data", usecols=range(0,10)) # 先转换日期格式、按ID和日期排序保证顺序正确 data['Date'] = pd.to_datetime(data['Date']) data = data.sort_values(['ID', 'Date']).reset_index(drop=True) # 分组取前一行的Stock值即为前1天同ID的Stock总和 data['SUMIF'] = data.groupby('ID')['Stock'].shift(1).fillna(0)
方案2:同ID同一天存在多条记录时使用(通用兼容)
如果同一个ID同一天可能有多个行,先按ID和日期聚合Stock总和再做关联匹配即可:
import pandas as pd data = pd.read_excel(settings['input_file'], sheet_name = "Data", usecols=range(0,10)) data['Date'] = pd.to_datetime(data['Date']) # 第一步:按ID+日期聚合当天所有Stock的总和 daily_stock = data.groupby(['ID', 'Date'], as_index=False)['Stock'].sum() # 第二步:给聚合后的日期加1天作为关联键,匹配原表中后一天的记录 daily_stock['match_date'] = daily_stock['Date'] + pd.Timedelta(days=1) # 第三步:左关联回原表拿到对应前一天的Stock总和 data = data.merge( daily_stock[['ID', 'match_date', 'Stock']], left_on=['ID', 'Date'], right_on=['ID', 'match_date'], how='left' ).rename(columns={'Stock_y': 'SUMIF'}).drop(columns=['match_date']) # 无匹配的空值(无对应前一天数据的行)填0 data['SUMIF'] = data['SUMIF'].fillna(0)
性能说明
两种方案在100万行数据集上的运行时间通常在1秒以内,相比原逐行apply方案提速可达上千倍。
内容的提问来源于stack exchange,提问作者Lyesgigs
相关产品推荐
相关产品推荐

