OneHotEncoder处理测试数据时触发isnan TypeError问题排查
问题描述
计算线性回归与树模型特征重要性时,在测试数据的OneHotEncoder处理阶段触发如下错误:
TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
数据集存在空值,核心疑惑:
- 训练集包含同样空值却未报错
- 空值是否不被
OneHotEncoder支持 - 如何解决该问题
相关代码
# 读取训练数据集 df_train = pd.read_excel('/content/feature importance training profiles.xlsx') # train_shuffled = df_train.sample(frac=1) # 划分训练集特征与标签 x_df_train = df_train[['Name', 'middleName', 'lastnName', 'Certification', 'Location', 'College', 'Degree', 'Jobs', 'Company', 'Date', 'LocationJob']] y_df_train = df_train['Label'] # 训练集特征独热编码 skencoder = OneHotEncoder(handle_unknown='ignore') sk_data_train = skencoder.fit_transform(x_df_train[['Name', 'middleName', 'lastnName', 'Certification', 'Location', 'College', 'Degree', 'Jobs', 'Company', 'Date', 'LocationJob']]) # 读取测试数据集 df_test = pd.read_excel('/content/feature importance testing profiles.xlsx') # test_shuffled = df_test.sample(frac=1) # 划分测试集特征与标签 x_df_test = df_test[['Name', 'middleName', 'lastnName', 'Certification', 'Location', 'College', 'Degree', 'Jobs', 'Company', 'Date', 'LocationJob']] y_df_test = df_test['Label'] # 测试集特征独热编码(触发错误) sk_data_test = skencoder.transform(x_df_test[['Name', 'middleName', 'lastnName', 'Certification', 'Location', 'College', 'Degree', 'Jobs', 'Company', 'Date', 'LocationJob']]) X, y = make_classification( n_samples=63, n_features=11, n_informative=11, n_redundant=0, n_repeated=0, n_classes=2, random_state=0, shuffle=True, ) # X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=42) feature_names = [f"feature {i}" for i in range(X.shape[1])] forest = RandomForestClassifier(random_state=0) forest.fit(sk_data_train, y_df_train) importance = forest.feature_importances_ print(importance) std = np.std([tree.feature_importances_ for tree in forest.estimators_], axis=0) forest_importances = pd.Series(importance, index=feature_names) fig, ax = plt.subplots() forest_importances.plot.bar(yerr=std, ax=ax) ax.set_title("Feature importances using MDI") ax.set_ylabel("Mean decrease in impurity") fig.tight_layout() y_pred = forest.predict(sk_data_test) print("ACCURACY OF THE MODEL: ", metrics.accuracy_score(y_df_test, y_pred))
问题分析与解决方案
核心原因
- 空值类型不统一:训练集的空值可能是字符串类型(如空字符串
""),而测试集的空值是数值型空值(np.nan/pd.NA)。OneHotEncoder可以处理字符串类别的空值,但无法兼容数值型空值——内部调用isnan函数时,无法对字符串类型执行该操作,触发类型不匹配错误。 OneHotEncoder的空值支持限制:该编码器不原生支持数值型空值,仅能处理离散的类别值(包括字符串类型的空值)。
训练集未报错的原因
训练集读取时,空值可能被自动转换为字符串类型(如Excel空白单元格被读取为空字符串),OneHotEncoder将其当作普通类别完成fit操作;而测试集的空值被读取为np.nan(数值型空),transform时触发类型冲突。
解决方案
方案1:统一空值为特定类别
将训练集和测试集的所有空值替换为统一的类别(如"Missing"),确保数据类型一致:
# 处理训练集空值 x_df_train = x_df_train.fillna("Missing") # 处理测试集空值 x_df_test = x_df_test.fillna("Missing")
方案2:强制统一特征类型
将所有特征列转换为字符串类型,避免混合类型导致的错误:
# 转换训练集特征为字符串 x_df_train = x_df_train.astype(str) # 转换测试集特征为字符串 x_df_test = x_df_test.astype(str) # 把转换后出现的"nan"字符串替换为统一类别 x_df_train = x_df_train.replace("nan", "Missing") x_df_test = x_df_test.replace("nan", "Missing")
方案3:删除含空值的样本(不推荐,会丢失数据)
如果空值样本占比极低,可以直接删除:
x_df_train = x_df_train.dropna() y_df_train = y_df_train.loc[x_df_train.index] x_df_test = x_df_test.dropna() y_df_test = y_df_test.loc[x_df_test.index]
内容的提问来源于stack exchange,提问作者Jesper Ezra
相关产品推荐
相关产品推荐

