迭代Pandas DataFrame时触发List index out of range错误求助
问题解析与修复方案
核心问题解答
A. 移除条件后为何正常?
带条件时,service.append()仅在rt_type[i] == 'AFEL'且muni[i] == 'Vestavia Hills'时执行,不是每轮循环都追加元素。当条件不满足时,service列表长度会落后于其他列表(比如travel、disp),此时用service[i]访问会触发索引越界——i是df的行索引,对应其他列表已有i+1个元素,但service的元素数量不足。
移除条件后,每轮循环都会执行service.append(),列表长度和其他列表完全同步,service[i]自然能正常访问。
B. 为何travel未出现索引错误?
travel.append((miles[i])/22)是每轮循环必执行的操作,travel列表的长度始终和df的行数一致,i作为当前循环的行索引,travel[i]永远能找到对应位置的元素,不会出现越界。
深层隐患:lookup循环的bug
你的lookup嵌套循环存在两个问题:
- 如果
df中某条Route Number在lookup表中无匹配项,rt_type和muni列表不会追加元素,后续访问rt_type[i]或muni[i]同样会触发索引越界。 - 如果
lookup表中存在重复的Route值,会多次追加rt_type和muni,导致这两个列表长度超出其他列表,后续逻辑也会出错。
修复方案
1. 先解决service的索引越界问题
确保每轮循环都给service追加元素,添加默认分支:
# 替换原service条件代码 if rt_type[i] == 'AFEL' and muni[i] == 'Vestavia Hills': service.append((stops[i]*17)/3600) else: # 根据业务需求设置默认值,比如0或其他计算逻辑 service.append(0)
2. 修复lookup匹配逻辑
用字典映射替代嵌套循环,避免索引不一致问题:
# 先将lookup表转为字典,实现O(1)快速查找 route_lookup = lookup.set_index('Route')[['Route Type', 'Municipality']].to_dict('index') # 在循环中直接查找,同时处理无匹配的情况 for i, row in df.iterrows(): route_num = df.at[i, 'Route Number'] # 找不到匹配时返回默认值,避免列表长度不一致 route_info = route_lookup.get(route_num, {'Route Type': 'UNKNOWN', 'Municipality': 'UNKNOWN'}) rt_type.append(str(route_info['Route Type'])) muni.append(str(route_info['Municipality'])) # 其余原有代码保持不变...
3. 更优的Pandas向量化写法(彻底规避列表迭代问题)
手动维护列表既低效又容易出错,直接用Pandas的向量化操作更可靠:
import numpy as np # 处理日期、线路编号拆分等基础字段 df['date'] = df['Route Date'].dt.strftime('%Y-%m-%d') df['dow'] = df['Route Number'].str[0] df['rt'] = df['Route Number'].str[1:4] # 合并lookup表,自动匹配线路类型和 municipality df = df.merge(lookup, left_on='Route Number', right_on='Route', how='left') # 处理无匹配的线路,填充默认值 df['Route Type'] = df['Route Type'].fillna('UNKNOWN').astype(str) df['Municipality'] = df['Municipality'].fillna('UNKNOWN').astype(str) # 计算各衍生字段 df['travel'] = df['Miles'] / 22 df['service'] = np.where( (df['Route Type'] == 'AFEL') & (df['Municipality'] == 'Vestavia Hills'), (df['Stops']*17)/3600, 0 # 替换为你的业务默认值 ) df['disp'] = df['Disposal Loads'] * (22/60) df['pre_post'] = 0.78 df['target_clk_hrs'] = df['travel'] + df['service'] + df['disp'] + 1.28 df['variance'] = df['target_clk_hrs'] - df['Clock Hours'] # 生成最终的新DataFrame df2 = df[['date', 'dow', 'rt', 'Route Type', 'Municipality', 'Miles', 'Disposal Tons', 'Disposal Loads', 'Stops', 'Clock Hours', 'travel', 'service', 'disp', 'pre_post', 'target_clk_hrs', 'variance']]
内容的提问来源于stack exchange,提问作者sweeney
相关产品推荐
相关产品推荐

