Pandas 使用 .iloc 绘图时报 DataFrame indexer 错误如何解决?
将两处 data['timestamp'].iloc[X_test] 改为 data.loc[X_test.index, 'timestamp'] 即可。X_test 是包含特征数据的 DataFrame,不能直接作为 .iloc 的行索引。查找时间戳时,需要使用它保留的行索引标签。
为什么会报错?
原代码中的:
X = data[['time_num', 'temp']]
创建了一个包含两列特征的 DataFrame。经过 train_test_split 后,X_test 仍然是 DataFrame,并保留了抽中行的原始索引标签。
.iloc 按整数位置选取数据,例如 .iloc[0] 或 .iloc[[0, 2]],不接受整个 DataFrame 作为索引器,因此下面的写法会报错:
data['timestamp'].iloc[X_test]
直接改成 .loc[X_test] 也不行,因为传入的仍然是特征表。list(X_test) 得到的是列名列表 ['time_num', 'temp'],也不是测试集的行索引。
如何修改绘图代码?
保留读取数据、划分训练集和训练模型的代码,将预测及绘图部分改为:
y_pred = model.predict(X_test)
# 按 X_test 的行顺序提取对应时间戳
test_timestamps = data.loc[X_test.index, 'timestamp']
plt.figure(figsize=(15, 5))
plt.scatter(
test_timestamps,
y_test,
s=5,
alpha=0.5,
label="Actual"
)
plt.scatter(
test_timestamps,
y_pred,
s=5,
alpha=0.5,
color='red',
label="Predicted"
)
plt.xlabel("Datetime")
plt.ylabel("Load")
plt.title("Energy Load:Actual vs Predicted")
plt.legend()
plt.tight_layout()
plt.show()
上面的 test_timestamps 赋值语句应顶格书写:
test_timestamps = data.loc[X_test.index, 'timestamp']
也可以使用等价写法:
test_timestamps = data['timestamp'].loc[X_test.index]
为什么这些数据能够按行对应?
在原代码的处理流程中:
train_test_split(X, y, ...)会同步划分特征和目标值,因此X_test与y_test的行顺序一致。model.predict(X_test)返回的预测值顺序与传入的X_test行顺序一致。- 当
data的索引唯一时,data.loc[X_test.index, 'timestamp']按X_test.index的顺序取出时间戳。
这样,每个时间戳都对应同一条测试样本的实际值和预测值。随机划分后,测试集通常不按时间排序,但这不会影响散点图的对应关系。不要单独对时间戳排序,否则会打乱它与两组纵坐标的配对。
能否继续使用 .iloc?
原代码直接使用 pd.read_csv(path),没有设置 index_col,也没有修改行索引。此时,默认整数索引标签与行位置一致,因此下面的写法也适用:
test_timestamps = data['timestamp'].iloc[X_test.index]
这种写法依赖索引标签恰好等于行位置。筛选数据、重新排序或设置其他索引后,这个前提可能不再成立。这里是根据测试集保留的索引标签查找原始行,使用 .loc 更贴合操作目的。
如果后续处理引入了重复索引标签,需要先确保每条样本有唯一且在划分前后保持一致的行标识。否则,.loc 按重复标签选择时可能返回额外行,影响绘图配对。
备注:内容仅供参考。
