PAYATHON 2026

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 按重复标签选择时可能返回额外行,影响绘图配对。

备注:内容仅供参考。