解决IndexError: single positional indexer is out-of-bounds并跳过无数据股票
问题
我写了一段Python代码用来获取印度股市历史数据,每天收盘后(大概20:00-21:00)运行。多数时候能正常输出,但经常触发IndexError: single positional indexer is out-of-bounds异常。排查后发现是部分股票的交易所数据没更新,导致程序直接中断,没法输出其他已经更新的股票结果。需要修改代码,实现跳过无数据的股票,正常处理剩下的股票。
原代码如下:
from datetime import date from datetime import timedelta from nsepy import get_history import pandas as pd import datetime # import matplotlib.pyplot as mp end1 = date.today() start1 = end1 - timedelta(days=365) stock = [ 'RELIANCE','HDFCBANK','INFY','ICICIBANK','HDFC','TCS','KOTAKBANK','LT','SBIN','HINDUNILVR','AXISBANK','ITC','BAJFINANCE','BHARTIARTL','ASIANPAINT','HCLTECH','MARUTI','TITAN','BAJAJFINSV','TATAMOTORS', 'TECHM','SUNPHARMA','TATASTEEL','M&M','WIPRO','ULTRACEMCO','POWERGRID','HINDALCO','NTPC','NESTLEIND','GRASIM','ONGC','JSWSTEEL','HDFCLIFE','INDUSINDBK','SBILIFE','DRREDDY','ADANIPORTS','DIVISLAB','CIPLA', 'BAJAJ-AUTO','TATACONSUM','UPL','BRITANNIA','BPCL','EICHERMOT','HEROMOTOCO','COALINDIA','SHREECEM','IOC','VEDL','ADANIENT', 'APOLLOHOSP', 'TATAPOWER', 'PIDILITIND', 'SRF', 'NAUKRI', 'ICICIGI', 'DABUR', 'GODREJCP', 'HAVELLS', 'PEL', 'VOLTAS', 'AUBANK', 'LTI', 'CHOLAFIN', 'AMBUJACEM', 'MARICO', 'SRTRANSFIN','GAIL', 'MCDOWELL-N', 'MPHASIS', 'MINDTREE', 'PAGEIND', 'ZEEL', 'BEL', 'TRENT', 'CROMPTON', 'JUBLFOOD', 'DLF', 'SBICARD', 'SIEMENS', 'BANDHANBNK', 'IRCTC', 'LAURUSLABS', 'PIIND', 'INDIGO', 'INDUSTOWER','ICICIPRULI', 'MOTHERSON', 'AARTIIND', 'FEDERALBNK', 'BANKBARODA', 'PERSISTENT', 'HINDPETRO', 'ACC', 'AUROPHARMA', 'COLPAL', 'GODREJPROP', 'MFSL', 'LUPIN', 'BIOCON', 'ASHOKLEY', 'BHARATFORG', 'BERGEPAINT','JINDALSTEL', 'ASTRAL', 'IEX', 'NMDC', 'CONCOR', 'INDHOTEL', 'BALKRISIND', 'PETRONET', 'CANBK', 'ALKEM', 'DIXON', 'DEEPAKNTR', 'DALBHARAT', 'TVSMOTOR', 'ATUL', 'HDFCAMC', 'TATACOMM', 'MUTHOOTFIN', 'TATACHEM','SAIL', 'IDFCFIRSTB', 'PFC', 'BOSCHLTD', 'MRF', 'NAVINFLUOR', 'CUMMINSIND', 'IGL', 'IPCALAB', 'COFORGE', 'ESCORTS', 'TORNTPHARM', 'LTTS', 'RECLTD', 'LICHSGFIN', 'BATAINDIA', 'HAL', 'PNB', 'GUJGASLTD', 'UBL','3MINDIA','ABB','AIAENG','APLAPOLLO','AARTIDRUGS','AAVAS','ABBOTINDIA','ADANIGREEN','ATGL','ABCAPITAL', 'ABFRL','ABSLAMC','ADVENZYMES','AEGISCHEM','AFFLE','AJANTPHARM','ALKYLAMINE','ALLCARGO','AMARAJABAT','AMBER','ANGELONE','ANURAS','APTUS','ASAHIINDIA','ASTERDM','ASTRAZEN','AVANTIFEED','DMART','BASF', 'BSE','BAJAJELEC','BAJAJHLDNG','BALAMINES','BALRAMCHIN','BANKINDIA','MAHABANK','BAYERCROP','BDL','BEL','BHEL','BIRLACORPN','BSOFT','BLUEDART','BLUESTARCO','BORORENEW','BOSCHLTD','BRIGADE','BCG','MAPMYINDIA' ] target_stocks_list = [] target_stocks = pd.DataFrame() for stock in stock: vol = get_history(symbol=stock, start=start1, end=end1) d_vol = pd.concat([vol['Deliverable Volume']]) symbol_s = pd.concat([vol['Symbol']]) close = pd.concat([vol['Close']]) df = pd.DataFrame(symbol_s) df['D_vol'] = d_vol # print(df) cond = df['D_vol'].iloc[-1] > max(df['D_vol'].iloc[-91:-1]) if(cond): target_stocks_list.append(stock) target_stocks = pd.concat([target_stocks, df]) print(target_stocks_list) file_name = f'{datetime.datetime.now().day}-{datetime.datetime.now().month}-{datetime.datetime.now().year}.csv' target_stocks.to_csv(f'D:/HUGE VOLUME SPURTS/first 250/SEP 2022/{file_name}') pd.set_option('display.max_columns',10) pd.set_option('display.max_rows',2000) print(target_stocks)
报错信息:
Traceback (most recent call last): File "C:\Users\Yogesh_PC\PycharmProjects\future oi data analysis\trial2.py", line 64, in <module> cond = df['D_vol'].iloc[-1] > max(df['D_vol'].iloc[-91:-1]) File "C:\python\Python310\lib\site-packages\pandas\core\indexing.py", line 967, in __getitem__ return self._getitem_axis(maybe_callable, axis=axis) File "C:\python\Python310\lib\site-packages\pandas\core\indexing.py", line 1520, in _getitem_axis self._validate_integer(key, axis) File "C:\python\Python310\lib\site-packages\pandas\core\indexing.py", line 1452, in _validate_integer raise IndexError("single positional indexer is out-of-bounds") IndexError: single positional indexer is out-of-bounds
比如如果股票列表里的'IRCTC'数据没更新,程序就会因为这个股票中断,没法输出其他已更新股票的结果。
修改后的代码
from datetime import date from datetime import timedelta from nsepy import get_history import pandas as pd import datetime end1 = date.today() start1 = end1 - timedelta(days=365) stock = [ 'RELIANCE','HDFCBANK','INFY','ICICIBANK','HDFC','TCS','KOTAKBANK','LT','SBIN','HINDUNILVR','AXISBANK','ITC','BAJFINANCE','BHARTIARTL','ASIANPAINT','HCLTECH','MARUTI','TITAN','BAJAJFINSV','TATAMOTORS', 'TECHM','SUNPHARMA','TATASTEEL','M&M','WIPRO','ULTRACEMCO','POWERGRID','HINDALCO','NTPC','NESTLEIND','GRASIM','ONGC','JSWSTEEL','HDFCLIFE','INDUSINDBK','SBILIFE','DRREDDY','ADANIPORTS','DIVISLAB','CIPLA', 'BAJAJ-AUTO','TATACONSUM','UPL','BRITANNIA','BPCL','EICHERMOT','HEROMOTOCO','COALINDIA','SHREECEM','IOC','VEDL','ADANIENT', 'APOLLOHOSP', 'TATAPOWER', 'PIDILITIND', 'SRF', 'NAUKRI', 'ICICIGI', 'DABUR', 'GODREJCP', 'HAVELLS', 'PEL', 'VOLTAS', 'AUBANK', 'LTI', 'CHOLAFIN', 'AMBUJACEM', 'MARICO', 'SRTRANSFIN','GAIL', 'MCDOWELL-N', 'MPHASIS', 'MINDTREE', 'PAGEIND', 'ZEEL', 'BEL', 'TRENT', 'CROMPTON', 'JUBLFOOD', 'DLF', 'SBICARD', 'SIEMENS', 'BANDHANBNK', 'IRCTC', 'LAURUSLABS', 'PIIND', 'INDIGO', 'INDUSTOWER','ICICIPRULI', 'MOTHERSON', 'AARTIIND', 'FEDERALBNK', 'BANKBARODA', 'PERSISTENT', 'HINDPETRO', 'ACC', 'AUROPHARMA', 'COLPAL', 'GODREJPROP', 'MFSL', 'LUPIN', 'BIOCON', 'ASHOKLEY', 'BHARATFORG', 'BERGEPAINT','JINDALSTEL', 'ASTRAL', 'IEX', 'NMDC', 'CONCOR', 'INDHOTEL', 'BALKRISIND', 'PETRONET', 'CANBK', 'ALKEM', 'DIXON', 'DEEPAKNTR', 'DALBHARAT', 'TVSMOTOR', 'ATUL', 'HDFCAMC', 'TATACOMM', 'MUTHOOTFIN', 'TATACHEM','SAIL', 'IDFCFIRSTB', 'PFC', 'BOSCHLTD', 'MRF', 'NAVINFLUOR', 'CUMMINSIND', 'IGL', 'IPCALAB', 'COFORGE', 'ESCORTS', 'TORNTPHARM', 'LTTS', 'RECLTD', 'LICHSGFIN', 'BATAINDIA', 'HAL', 'PNB', 'GUJGASLTD', 'UBL','3MINDIA','ABB','AIAENG','APLAPOLLO','AARTIDRUGS','AAVAS','ABBOTINDIA','ADANIGREEN','ATGL','ABCAPITAL', 'ABFRL','ABSLAMC','ADVENZYMES','AEGISCHEM','AFFLE','AJANTPHARM','ALKYLAMINE','ALLCARGO','AMARAJABAT','AMBER','ANGELONE','ANURAS','APTUS','ASAHIINDIA','ASTERDM','ASTRAZEN','AVANTIFEED','DMART','BASF', 'BSE','BAJAJELEC','BAJAJHLDNG','BALAMINES','BALRAMCHIN','BANKINDIA','MAHABANK','BAYERCROP','BDL','BEL','BHEL','BIRLACORPN','BSOFT','BLUEDART','BLUESTARCO','BORORENEW','BOSCHLTD','BRIGADE','BCG','MAPMYINDIA' ] target_stocks_list = [] target_stocks = pd.DataFrame() for stock_sym in stock: try: vol = get_history(symbol=stock_sym, start=start1, end=end1) # 检查返回的DataFrame是否为空 if vol.empty: print(f"无数据,跳过股票: {stock_sym}") continue # 直接提取列构造DataFrame,无需多余的pd.concat df = pd.DataFrame({ 'Symbol': vol['Symbol'], 'D_vol': vol['Deliverable Volume'] }) # 确保数据长度足够,避免索引越界 if len(df) < 91: print(f"数据不足91条,跳过股票: {stock_sym}") continue # 计算条件,使用pandas内置max方法更高效 latest_vol = df['D_vol'].iloc[-1] past_90_max = df['D_vol'].iloc[-91:-1].max() if latest_vol > past_90_max: target_stocks_list.append(stock_sym) target_stocks = pd.concat([target_stocks, df]) except Exception as e: print(f"处理股票 {stock_sym} 时出错: {str(e)}") continue print(target_stocks_list) file_name = f'{datetime.datetime.now().day}-{datetime.datetime.now().month}-{datetime.datetime.now().year}.csv' target_stocks.to_csv(f'D:/HUGE VOLUME SPURTS/first 250/SEP 2022/{file_name}') pd.set_option('display.max_columns',10) pd.set_option('display.max_rows',2000) print(target_stocks)
关键修复点
- 异常捕获机制:用
try-except包裹单只股票的处理逻辑,任何异常都会触发跳过操作,保证程序继续处理下一只股票。 - 空数据校验:调用接口后先判断返回的数据集是否为空,为空直接跳过该股票。
- 数据长度检查:确保数据至少有91条记录,避免
iloc[-91:-1]出现索引越界问题。 - 代码优化:去掉不必要的
pd.concat操作,直接用字典构造DataFrame;替换Python内置max()为pandas的max()方法,提升处理效率。 - 变量名修正:将循环变量从
stock改为stock_sym,避免与股票列表变量名冲突。
内容的提问来源于stack exchange,提问作者user19696249
相关产品推荐
相关产品推荐

