R语言for循环运行KNN选k值时列表前29项为空如何解决
问题原因
- 最核心的原因是没有提前初始化
pre为固定长度的列表:如果循环前你只是用pre <- list()创建了空列表,甚至把pre定义成了原子向量/矩阵类型,就会出现赋值异常。- 如果
pre是原子向量(比如你之前用pre <- c()初始化),knn返回的是长度等于测试集样本数的因子向量,无法存入原子向量的单个位置,R会自动丢弃前面的赋值,仅保留最后一次的有效赋值。 - 如果
pre是未指定长度的空列表,R循环中动态扩展列表时可能因为内存分配、环境变量残留的问题,导致前面索引位置的赋值没有被正确写入,仅最后一次赋值成功。
- 如果
- 次要可能是变量名冲突:如果你的工作环境里之前定义过
pre、l、k相关的变量,残留值会干扰循环赋值。
修正代码
首先要加载class包(knn函数的依赖),提前初始化存储结构,再跑循环:
# 加载依赖包 library(class) # 初始化存储结构:pre存预测结果,accuracy存对应准确率 k_range <- 1:30 pre <- vector("list", length(k_range)) # 明确初始化长度为30的列表 accuracy <- numeric(length(k_range)) # 初始化数值向量存准确率 # 循环遍历k值 for (l in k_range) { # 生成预测结果 pre[[l]] <- knn(train = train_dataset, test = test_dataset, cl = labels_train, k = l) # 计算当前k的准确率,注意labels_test替换为你自己的测试集真实标签变量名 accuracy[l] <- mean(pre[[l]] == labels_test) } # 查看所有k的准确率 print(accuracy) # 找最优k best_k <- which.max(accuracy) cat("最优k值为:", best_k, ",对应准确率为:", accuracy[best_k])
背后原理
- R的存储结构分为原子向量和递归向量(列表):原子向量的每个位置只能存单个基础类型值(数值、字符、逻辑值等),列表的每个位置可以存任意类型的对象(向量、矩阵、模型对象都可以)。如果用原子向量存knn返回的多元素预测向量,必然会出现赋值失败。
- 提前初始化固定长度的存储结构,会提前在内存中分配对应大小的空间,不需要循环中动态申请内存,既提升了运行效率,也避免了动态扩展时的内存分配异常导致的赋值丢失。
- 循环前清理环境变量(可以用
rm(list = ls())清理,注意保存必要数据)也可以避免历史变量残留导致的冲突。
内容的提问来源于stack exchange,提问作者Yagami_Light
相关产品推荐
相关产品推荐

