Pandas从外部文件为DataFrame赋值时遇索引错误及NaN问题
问题分析与修复方案
错误原因拆解
- 索引越界:pandas的
iloc是从0开始的位置索引,原循环range(1, len(df)+1)会让i取到len(df),而DataFrame的最大位置索引是len(df)-1,直接触发IndexError。 - 赋值无效:
df.iloc[i]['Up_Time']属于链式索引,返回的是原DataFrame的副本,修改副本不会影响原数据,导致初始设置的NaN无法被覆盖。 - 列名大小写不匹配:原DataFrame的列是
Down_Time,但代码里写的是Down_time(小写t),会新增错误列,目标列根本没被赋值。 - 匹配结果处理不当:
new_df['Up_Time']返回的是Series,直接赋值给单个单元格会导致类型不匹配,必须提取标量值。
修正后的代码(循环版)
import pandas as pd import numpy as np # 初始化列名与原DataFrame保持一致 df['Up_Time'] = np.nan df['Down_Time'] = np.nan # 循环从0开始,遍历所有行的位置索引 for i in range(len(df)): time_val = df.iloc[i]['Time'] file_name = df.iloc[i]['File_name'] # 读取对应CSV文件(用f-string简化路径拼接) new_df = pd.read_csv(f"{path}{str(file_name)}.csv") # 精确匹配Time列,避免部分匹配错误 matched_rows = new_df[new_df['Time'] == time_val] # 确认匹配到数据再赋值 if not matched_rows.empty: up_time_val = matched_rows.iloc[0]['Up_Time'] down_time_val = matched_rows.iloc[0]['Down_Time'] # 直接修改原DataFrame的对应位置,避免链式索引 df.iloc[i, df.columns.get_loc('Up_Time')] = up_time_val df.iloc[i, df.columns.get_loc('Down_Time')] = down_time_val
更高效的apply版本
如果数据量较大,用apply替代循环更高效:
def fill_time_row(row): time_val = row['Time'] file_name = row['File_name'] new_df = pd.read_csv(f"{path}{str(file_name)}.csv") matched = new_df[new_df['Time'] == time_val] if not matched.empty: return pd.Series([matched.iloc[0]['Up_Time'], matched.iloc[0]['Down_Time']]) return pd.Series([np.nan, np.nan]) # 直接批量填充目标列 df[['Up_Time', 'Down_Time']] = df.apply(fill_time_row, axis=1)
额外注意事项
- 优先用
==精确匹配Time列,不要用str.contains,避免因时间字符串前缀相似导致错误匹配。 - 如果CSV文件与原DataFrame的
Time格式不一致,需先统一格式(比如转成datetime类型),否则会匹配不到数据。 - 若需处理大量CSV文件,建议缓存已读取的文件,避免重复IO操作浪费资源。
内容的提问来源于stack exchange,提问作者rakesh
相关产品推荐
相关产品推荐

