K折交叉验证代码报错:'(slice(None, None, None), 0)'无效键及iloc问题
K折交叉验证索引错误的解决方案
看起来你在实现K折交叉验证时踩了一个很常见的坑——混淆了pandas DataFrame和numpy数组的索引逻辑,我来帮你理清楚问题并修正代码。
错误原因分析
你遇到的两个错误本质上是同一个问题:
- 当你用
np.array_split(data, k)处理pandas DataFrame时,返回的是一个包含k个DataFrame的列表,而不是numpy数组。所以你用folds[i][:, 0]这种numpy式的索引会报错,因为DataFrame不支持这种索引语法。 - 之后尝试
folds.iloc[i]又报错,是因为folds是Python列表,而iloc是pandas DataFrame独有的方法,列表根本没有这个属性。
下面给你两种可行的修正方案,你可以根据自己的习惯选择:
方案一:纯Pandas/DataFrame操作(推荐,保持数据结构清晰)
这种方法保留DataFrame的结构,更适合后续的数据分析和预处理:
import pandas as pd import numpy as np data = pd.read_csv('Data_assignment1.csv') k = 10 # 正确打乱DataFrame:用sample方法,避免破坏数据结构 data_shuffled = data.sample(frac=1, random_state=42).reset_index(drop=True) # 分割成k个DataFrame组成的列表 folds = np.array_split(data_shuffled, k) for i in range(k): # 取出第i折作为验证集,用iloc获取列(或直接用列名更直观) cv_df = folds[i] x_cv = cv_df.iloc[:, 0].values # .values转成numpy数组(如果模型需要) y_cv = cv_df.iloc[:, 1].values # 合并剩余的k-1折作为训练集 train_dfs = folds[:i] + folds[i+1:] train_df = pd.concat(train_dfs, axis=0) x_train = train_df.iloc[:, 0].values y_train = train_df.iloc[:, 1].values # 这里插入你的模型训练、验证逻辑 print(f"第{i+1}折:训练样本数{len(train_df)},验证样本数{len(cv_df)}")
关键点说明:
- 用
data.sample(frac=1)打乱数据比直接np.random.shuffle(data.values)更安全,能保留DataFrame的列名和索引结构。 - 取验证集时,先从列表中取出对应的DataFrame,再用
iloc[:, 0]获取第一列(如果知道列名,比如cv_df['feature_col']会更易读)。 - 合并训练集时,用列表切片获取除第i折外的所有DataFrame,再用
pd.concat合并成一个大的DataFrame。
方案二:转成Numpy数组操作(适合习惯numpy的场景)
如果你更习惯用numpy数组处理数据,可以先把DataFrame转成numpy数组再操作:
import pandas as pd import numpy as np data = pd.read_csv('Data_assignment1.csv') k = 10 # 把DataFrame转成numpy数组 data_np = data.values # 打乱数组 np.random.shuffle(data_np) # 分割成k个numpy数组组成的列表 folds = np.array_split(data_np, k) for i in range(k): # 直接用numpy索引获取验证集 x_cv = folds[i][:, 0] y_cv = folds[i][:, 1] # 合并剩余折作为训练集 train_folds = np.delete(folds, i, 0) train_np = np.row_stack(train_folds) x_train = train_np[:, 0] y_train = train_np[:, 1] # 插入模型训练逻辑 print(f"第{i+1}折:训练样本数{len(train_np)},验证样本数{len(folds[i])}")
关键点说明:
- 先通过
data.values把DataFrame转成numpy数组,这样np.array_split返回的就是numpy数组的列表,就能用[:, 0]这种熟悉的索引方式了。 - 这种方法省去了DataFrame的操作,适合不需要保留列信息的场景。
内容的提问来源于stack exchange,提问作者sabrina
相关产品推荐
相关产品推荐

