如何在for循环中更新Pandas DataFrame?KFold训练集大小疑问
问题解答
一、DataFrame存储系数报错的解决方法
你遇到的None of [Int64Index(...)] are in the [columns]错误,核心原因是你试图用训练集的观测行索引作为DataFrame的列名,但空DataFramevar一开始没有这些列,而且逻辑上也不应该这么存储系数。
你的需求是存储每次迭代(每个折叠)后的变量系数,正确的做法应该是把折叠次数或特征作为维度来组织数据,下面给你两种实用的实现方式:
方式1:按折叠次数作为行,特征作为列
这种方式适合查看每个折叠下所有特征的系数情况:
from sklearn.model_selection import KFold import pandas as pd import matplotlib.pyplot as plt from sklearn.linear_model import Lasso kf = KFold(n_splits=10) cvlasso= Lasso(alpha=0.001) count = 1 # 提前用特征名初始化DataFrame的列 var = pd.DataFrame(columns=X.columns) for train, _ in kf.split(X, Y): cvlasso.fit(X.iloc[train, :], Y.iloc[train]) importances_index_desc = cvlasso.coef_ feature_labels = list(X.columns.values) # 绘图部分保持不变 plt.figure() plt.bar(feature_labels, importances_index_desc) plt.xticks(feature_labels, rotation='vertical') plt.ylabel('Importance') plt.xlabel('Features') plt.title('Fold {}'.format(count)) # 将当前折叠的系数作为一行加入DataFrame var.loc[f'Fold {count}'] = importances_index_desc count += 1 plt.show()
最终var的每一行对应一个折叠的所有特征系数,列是特征名称,后续可以轻松对比不同折叠下的系数变化。
方式2:按特征作为行,折叠次数作为列
如果更关注单个特征在所有折叠中的系数波动,可改用这种结构:
# 初始化时用特征名作为行索引 var = pd.DataFrame(index=X.columns) # 循环内替换存储逻辑: var[f'Fold {count}'] = importances_index_desc
二、训练集大小不是33000的原因
KFold的拆分规则是把数据集平均分成n_splits份,每次用1份做测试集,剩下的n_splits-1份做训练集。
你提到训练集大小是28512,我们可以反推:28512 ÷ 9 × 10 = 31680,这说明你的数据集实际有效观测数是31680,而非你以为的33000。可能的原因包括:
- 加载数据集时不小心过滤了部分行(比如删除了含缺失值的样本,或者索引不连续)
- 原始数据集的行数本身就是31680,之前的统计有误
你可以先运行print(X.shape)确认数据集的实际行数,如果输出是(31680, N)(N为特征数),那训练集大小31680 × 9/10 = 28512完全符合KFold的拆分逻辑。
内容的提问来源于stack exchange,提问作者Warzone
相关产品推荐
相关产品推荐

