使用.dropna()后数据集尺寸不一致的处理方案咨询
解决训练/测试集DropNA后尺寸不一致及后续报错问题
核心问题分析
你遇到的两个报错,根源主要有三点:
- 训练集与测试集独立DropNA导致样本量不匹配:单独对训练集和测试集执行
df.dropna(inplace=True),会因两边缺失值分布不同,导致最终样本数差异,后续绘图和模型调用时出现维度冲突。 - 绘图代码中数组维度不匹配:
x1是一维数组((48571,)),而xmodel是二维特征矩阵((48470,9)),直接np.hstack会因维度不一致触发ValueError。 - OLS模型使用逻辑错误:你直接用未拟合的
reg_model调用predict,且用测试集训练模型再预测测试集的逻辑不符合机器学习流程(应该用训练集训练,测试集评估)。
分步解决方案
1. 统一处理缺失值,保证特征维度一致
不要分别对训练集和测试集执行DropNA,推荐两种合理的处理方式:
方案A(优先推荐:保留有效测试样本)
先处理训练集的缺失值,再单独过滤测试集中的缺失样本,保证两者特征维度一致:
# 处理训练集:DropNA并同步标签 X_train_clean = X_train.dropna() y_train_clean = y_train.loc[X_train_clean.index] # 处理测试集:仅保留无缺失值的样本 X_test_clean = X_test.dropna() y_test_clean = y_test.loc[X_test_clean.index] # 验证特征维度(列数必须一致) print(f"训练集形状:{X_train_clean.shape}") print(f"测试集形状:{X_test_clean.shape}")
这种方式不会强制对齐训练/测试集的样本数,而是保留各自的有效样本,符合机器学习评估的逻辑。
方案B(合并后统一清理)
如果希望尽量保留样本,可先合并训练和测试集,统一DropNA后再拆分回原分组:
# 给数据集打标签,方便后续拆分 X_train['data_type'] = 'train' X_test['data_type'] = 'test' y_train['data_type'] = 'train' y_test['data_type'] = 'test' # 合并数据 X_combined = pd.concat([X_train, X_test]) y_combined = pd.concat([y_train, y_test]) # 统一DropNA X_combined_clean = X_combined.dropna() y_combined_clean = y_combined.loc[X_combined_clean.index] # 拆分回训练/测试集 X_train_clean = X_combined_clean[X_combined_clean['data_type'] == 'train'].drop('data_type', axis=1) y_train_clean = y_combined_clean[y_combined_clean['data_type'] == 'train'].drop('data_type', axis=1) X_test_clean = X_combined_clean[X_combined_clean['data_type'] == 'test'].drop('data_type', axis=1) y_test_clean = y_combined_clean[y_combined_clean['data_type'] == 'test'].drop('data_type', axis=1)
2. 修正绘图代码,解决维度不匹配问题
想要绘制类似statsmodels示例的拟合/预测图,需要将所有绘图用的数组统一为一维,同时区分训练集和测试集的展示范围:
import numpy as np import matplotlib.pyplot as plt import statsmodels.api as sm # 生成训练集和测试集的x轴变量(用连续区间区分) x_train = np.linspace(0, 1, len(X_train_clean)) x_test = np.linspace(1, 2, len(X_test_clean)) # 训练OLS模型(注意添加截距项,statsmodels默认不含) X_train_with_intercept = sm.add_constant(X_train_clean) model = sm.OLS(y_train_clean, X_train_with_intercept) results = model.fit() # 得到训练集拟合值和测试集预测值 y_train_pred = results.predict(X_train_with_intercept) X_test_with_intercept = sm.add_constant(X_test_clean) y_test_pred = results.predict(X_test_with_intercept) # 绘图 fig, ax = plt.subplots(figsize=(10,6)) ax.plot(x_train, y_train_clean, 'o', alpha=0.5, label="Training Data") ax.plot(x_train, y_train_pred, 'b-', label="OLS Fit (Training)") ax.plot(x_test, y_test_clean, 's', alpha=0.5, label="Test Data") ax.plot(x_test, y_test_pred, 'r-', label="OLS Prediction (Test)") ax.legend(loc="best") ax.set_xlabel("Sample Range") ax.set_ylabel("Target Value");
3. 修正OLS模型评估代码,计算RMSE
你需要用训练好的模型预测测试集,再计算评估指标,代码逻辑如下:
from sklearn.metrics import mean_squared_error # 用训练好的模型预测测试集 y_test_pred = results.predict(X_test_with_intercept) # 计算RMSE(squared=False返回RMSE,True返回MSE) ols_rmse = mean_squared_error(y_test_clean, y_test_pred, squared=False) print(f"OLS RMSE on Test Set: {ols_rmse:.4f}")
这样就能得到OLS模型在测试集上的RMSE,方便和logit/lasso/SVC等模型的评估结果对比。
额外注意事项
- 禁止在测试集上训练模型:你的原代码中用测试集训练
reg_test是错误的,完全失去了模型评估的意义,必须用训练集训练模型,测试集仅用于评估。 - 缺失值处理的一致性:如果选择填充缺失值(而非DropNA),必须用训练集的统计量(均值/中位数)填充测试集,避免数据泄露。
内容的提问来源于stack exchange,提问作者Max D
相关产品推荐
相关产品推荐

