带条件多重for循环优化:pandas按日期间隔匹配映射权重Poids值
原有嵌套循环采用iterrows遍历,时间复杂度为O(n*m),13万行数据量下性能极低,以下是两种高效实现方案,运行耗时可缩短至秒级:
前置预处理
首先统一所有日期列的格式为datetime类型,这是后续匹配的基础:
# 将df1的起止日期转为datetime类型 df1['Start Date'] = pd.to_datetime(df1['Start Date']) df1['End Date'] = pd.to_datetime(df1['End Date']) # 你原有代码已经处理过Poids1的Date列,这里无需重复操作
方案1:IntervalIndex分组映射(性能最优)
适合同一个ID在df1中无重叠日期区间的场景,利用pandas内置的区间索引能力完成快速匹配:
def map_poids(group): # 取出当前ID对应的区间和权重数据 current_id_df = df1[df1['ID'] == group.name] # 构建闭区间索引,包含起止日期端点 interval_idx = pd.IntervalIndex.from_arrays( current_id_df['Start Date'], current_id_df['End Date'], closed='both' ) # 批量匹配当前组所有日期对应的权重 return group['Date'].apply( lambda x: current_id_df.loc[interval_idx.get_loc(x), 'Poids'] if any(interval_idx.contains(x)) else None ) Poids1['Poids'] = Poids1.groupby('ID', group_keys=False).apply(map_poids)
方案2:关联后过滤(写法简单兼容性强)
适合存在重叠区间、或者需要更直观写法的场景,先按ID关联两张表再过滤符合条件的行:
# 按ID关联两张表 temp_merged = Poids1.merge(df1, on='ID', how='left') # 过滤出日期落在起止区间内的匹配结果 matched = temp_merged[ (temp_merged['Date'] >= temp_merged['Start Date']) & (temp_merged['Date'] <= temp_merged['End Date']) ] # 去重(如果同一个ID和日期匹配到多个区间,默认保留第一个,可根据需求调整去重规则) matched = matched.drop_duplicates(subset=['ID', 'Date'], keep='first') # 将匹配到的权重赋值回原表 Poids1 = Poids1.merge( matched[['ID', 'Date', 'Poids_y']], on=['ID', 'Date'], how='left' ).rename(columns={'Poids_y': 'Poids'}).drop(columns=['Poids_x'], errors='ignore')
注意事项
如果存在同一个ID、同一个日期匹配到多个区间的情况,可根据业务需求调整去重规则,比如取权重最大/最小的结果。
内容的提问来源于stack exchange,提问作者Karl9929
相关产品推荐
相关产品推荐

