在R中运行kNN函数时遭遇NA错误的技术求助
问题描述
数据集
structure(list(Color = c(0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0,1,0, 0, 0, 1, 1, 0, 1, 0), Size = c(1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1,0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1), Act = c(1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0,1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1), Age = c(0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1,1,0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1), Inflated = c("F", "F", "F", "F", "F","F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T", "T")), row.names = c(NA, -28L), class = c("tbl_df", "tbl", "data.frame"))
运行代码
Inf_True <- originaldata%>% filter(Inflated == "T") Inf_False <- originaldata%>% filter(Inflated == "F") set.seed(4567) # samples ran_true <- sample(1:nrow(Inf_True), 0.8*nrow(Inf_True)) ran_false <- sample(1:nrow(Inf_False), 0.8*nrow(Inf_False)) ran <- sample(1:nrow(originaldata), 0.8*nrow(originaldata)) # Create training set Training_set <- rbind(Inf_True[ran_true,], Inf_False[ran_false,]) # Create testing set Test_set <- rbind(Inf_True[-ran_true,], Inf_False[-ran_false,]) # extract 5th column of train dataset because it will be used as 'cl' argument in knn function target_category <- originaldata[ran,5] a<-target_category$Inflated aa<-factor(a) # extract 5th column of test dataset to measure the accuracy test_category <- originaldata[-ran,5] library(class) ## Knn = 1 #run knn function print("Knn = 1") knn_one <- knn(Training_set, Test_set, cl=aa, k=1)
错误信息
Warning: NAs introduced by coercion
Warning: NAs introduced by coercion
Error in knn(Training_set, Test_set, cl = aa, k = 1) :
NA/NaN/Inf in foreign function call (arg 6)
问题排查与修正
核心问题1:特征集包含标签列,且分类标签与训练集不匹配
- 你构建的
Training_set和Test_set都包含了第5列Inflated(分类标签),但kNN的输入特征集必须只保留用于预测的特征列,标签列会干扰距离计算,导致错误。 - 你用
originaldata[ran,5]提取的标签aa,是从整个数据集随机抽样的结果,和分层抽样得到的Training_set样本完全不对应,导致标签长度、类别与训练集不匹配,进而产生NA和报错。
核心问题2:抽样行数为小数
0.8*nrow(Inf_True)计算结果是10.4,sample会自动向下取整,但显式处理为整数能避免潜在问题。
修正后的代码
library(dplyr) library(class) # 假设数据集已赋值给originaldata # originaldata <- structure(...) # 分层拆分正负样本 Inf_True <- originaldata %>% filter(Inflated == "T") Inf_False <- originaldata %>% filter(Inflated == "F") set.seed(4567) # 显式取整确保抽样行数为整数 ran_true <- sample(1:nrow(Inf_True), floor(0.8*nrow(Inf_True))) ran_false <- sample(1:nrow(Inf_False), floor(0.8*nrow(Inf_False))) # 构建训练/测试集,只保留特征列(去掉第5列Inflated) Training_set <- rbind(Inf_True[ran_true, -5], Inf_False[ran_false, -5]) Test_set <- rbind(Inf_True[-ran_true, -5], Inf_False[-ran_false, -5]) # 提取与训练集严格对应的标签 train_cl <- c(Inf_True$Inflated[ran_true], Inf_False$Inflated[ran_false]) train_cl <- factor(train_cl) # 提取测试集真实标签用于后续评估 test_cl <- c(Inf_True$Inflated[-ran_true], Inf_False$Inflated[-ran_false]) # 运行kNN print("Knn = 1") knn_one <- knn(Training_set, Test_set, cl = train_cl, k = 1) # 查看预测结果和准确率 table(knn_one, test_cl) mean(knn_one == test_cl)
关键修正点说明
- 特征集去标签列:
Training_set和Test_set仅保留Color/Size/Act/Age四个特征列。 - 标签与训练集严格匹配:直接从分层抽样后的子集提取标签,确保标签长度、类别与训练集完全对应。
- 整数抽样:用
floor()确保抽样行数为整数,避免隐性错误。
内容的提问来源于stack exchange,提问作者ano273
相关产品推荐
相关产品推荐

