You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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)

关键修正点说明

  1. 特征集去标签列:Training_set和Test_set仅保留Color/Size/Act/Age四个特征列。
  2. 标签与训练集严格匹配:直接从分层抽样后的子集提取标签,确保标签长度、类别与训练集完全对应。
  3. 整数抽样:用floor()确保抽样行数为整数,避免隐性错误。

内容的提问来源于stack exchange,提问作者ano273

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 02:28:13