基于多列匹配为Pandas DataFrame新增列报错及实现咨询
解决为optidx匹配对应futidx的CLOSE1值并处理无匹配的问题
咱们先拆解下你遇到的IndexError: single positional indexer is out-of-bounds错误:当optidx里的某一行在futidx中找不到SYMBOL、EXPIRY_DT、TIMESTAMP1完全匹配的记录时,futidx[(...)].iloc[0]就会因为返回的是空DataFrame而触发索引越界——空结果根本没有第0行可以取嘛!
下面给你两种解决办法,优先推荐第一种,不仅简洁还能搞定大数据量的场景:
方法一:用pd.merge实现高效匹配(强烈推荐)
这种方法是用数据库式的左连接来做匹配,比逐行遍历的apply效率高N倍,而且逻辑清晰不容易出错:
import pandas as pd # 读取CSV并解析日期字段 bhavcopy = pd.read_csv(path + bhavcopyfile, parse_dates=['EXPIRY_DT', 'TIMESTAMP']) print('Processing: ' + bhavcopyfile) # 处理特定文件的多余列 if bhavcopyfile != 'fo14MAY2012bhav.csv': bhavcopy = bhavcopy.drop('Unnamed: 15', axis=1) # 拆分futidx和optidx,同时重命名列避免后续混淆 futidx = bhavcopy[bhavcopy['INSTRUMENT'] == 'FUTIDX'].drop('INSTRUMENT', axis=1) futidx = futidx.rename(columns={'CLOSE': 'CLOSE1', 'TIMESTAMP': 'TIMESTAMP1'}) optidx = bhavcopy[bhavcopy['INSTRUMENT'] == 'OPTIDX'].drop('INSTRUMENT', axis=1) optidx = optidx.rename(columns={'CLOSE': 'CLOSE1', 'TIMESTAMP': 'TIMESTAMP1'}) # 只保留futidx中用于匹配的键和需要提取的CLOSE1字段 fut_mapping = futidx[['SYMBOL', 'EXPIRY_DT', 'TIMESTAMP1', 'CLOSE1']] # 左连接optidx和fut_mapping,按三个字段匹配 optidx = pd.merge( optidx, fut_mapping, on=['SYMBOL', 'EXPIRY_DT', 'TIMESTAMP1'], how='left', suffixes=('', '_fut') # 区分原CLOSE1和匹配来的CLOSE1 ) # 把匹配不到的空值填充为0,得到最终的fut_close列 optidx['fut_close'] = optidx['CLOSE1_fut'].fillna(0) # 不需要临时列的话可以删掉 optidx = optidx.drop('CLOSE1_fut', axis=1) print(optidx.head())
方法二:修复原apply的写法(适合小数据量场景)
如果你一定要用原来的apply思路,那得先判断匹配结果是否为空,再决定取值还是返回0:
# 替换你原来的apply行即可 optidx['fut_close'] = optidx.apply( lambda row: # 如果找到匹配行,取第一个CLOSE1值;否则返回0 futidx[ (futidx['SYMBOL'] == row['SYMBOL']) & (futidx['EXPIRY_DT'] == row['EXPIRY_DT']) & (futidx['TIMESTAMP1'] == row['TIMESTAMP1']) ]['CLOSE1'].iloc[0] if not futidx[ (futidx['SYMBOL'] == row['SYMBOL']) & (futidx['EXPIRY_DT'] == row['EXPIRY_DT']) & (futidx['TIMESTAMP1'] == row['TIMESTAMP1']) ].empty else 0, axis=1 )
⚠️ 注意:这种方法每一行要两次查询futidx,数据量大的时候会非常慢,所以只适合小数据集玩一玩~
另外提个小细节:你原来手动重命名列的时候,要注意和原CSV的列名对应(比如示例数据里是CLOSE不是CLOSE1),用rename方法会更安全,避免手动打错列名哦!
内容的提问来源于stack exchange,提问作者Dishant shah
相关产品推荐
相关产品推荐

