概念:K最近邻算法是一种惰性学习算法,它不对数据进行显式训练,而是直接将训练数据存储起来,分类时通过计算待分类样本与训练样本的距离来确定其类别。
原理:对于一个待分类的样本,在训练集中找出与其最相似的K个样本(近邻),这K个样本中哪个类别的样本最多,就将待分类样本归于该类。距离度量常用欧氏距离、曼哈顿距离等。
思想:“近朱者赤,近墨者黑”,即相似的样本应该具有相似的输出值或类别标签。
应用:适用于样本分布比较复杂、但类别边界不是特别清晰的场景,如手写数字识别、推荐系统(寻找相似用户或物品)。
-代码设置工作目录、清理环境。
-加载包:pacman, readxl, writexl, dplyr, caret, class, pROC, ggplot2, officer, flextable, gridExtra, showtext。
-设置中文字体支持。
-数据准备:读取Excel数据,转换分类变量为因子,分层抽样划分训练集和测试集。
-KNN模型:提取特征,标准化数据,使用交叉验证寻找最佳K值,训练KNN模型,预测。
-模型评估:计算准确率、混淆矩阵、AUC等。
-可视化:绘制ROC曲线和K值选择图。
-保存结果:输出预测结果、性能指标到Excel,生成Word报告。
-保存工作空间。
R语言代码实现了一个完整的KNN(K-最近邻)机器学习模型构建和分析流程,专为处理二元分类问题设计,涵盖了从数据准备到报告生成的自动化过程。
# 设置工作目录和清理环境
rm(list = ls())
if (!is.null(dev.list())) dev.off()
setwd("C:/Users/hyy/Desktop/")
# 创建结果文件夹
if (!dir.exists("Results-knn")) dir.create("Results-knn")
# 加载必要的包
if (!require(pacman)) install.packages("pacman")
pacman::p_load(readxl, writexl, dplyr, caret, class, pROC, ggplot2, officer, flextable, gridExtra, showtext)
# 设置全局中文字体支持
font_add(family = "simhei", regular = "simhei.ttf") # 添加黑体
font_add(family = "simsun", regular = "simsun.ttc") # 添加宋体
showtext_auto(enable = TRUE) # 启用showtext
# 设置图形设备参数(适用于基础绘图)
if (.Platform$OS.type == "windows") {
windowsFonts(SimHei = windowsFont("SimHei"))
windowsFonts(SimSun = windowsFont("SimSun"))
chinese_font <- "SimHei"
} else {
chinese_font <- "sans"
}
# 1. 数据准备
data <- read_excel("示例数据.xlsx")
# 将分类变量转换为因子
data$`肥胖程度` <- as.factor(data$`肥胖程度`)
data$`教育水平` <- as.factor(data$`教育水平`)
data$`血型` <- as.factor(data$`血型`)
data$`指标8` <- as.factor(data$`指标8`)
data$`结局` <- as.factor(data$`结局`)
# 分层抽样划分训练集和测试集
set.seed(1234)
train_index <- sample(1:nrow(data), nrow(data)*0.8) # 取80%做训练集
Train <- data[train_index, ]
Test <- data[-train_index, ]
# 保存数据集
write_xlsx(Train, "Results-knn/Train.xlsx")
write_xlsx(Test, "Results-knn/Test.xlsx")
write_xlsx(data, "Results-knn/All.xlsx")
# 2. KNN模型准备
# 提取需要的特征
Trainknn <- Train[, c("指标1", "指标2", "指标3", "指标4", "指标5", "指标6")]
Testknn <- Test[, c("指标1", "指标2", "指标3", "指标4", "指标5", "指标6")]
# 变量处理标准化
preProc <- preProcess(Trainknn, method = c("center", "scale"))
Trainknn_scaled <- predict(preProc, Trainknn)
Testknn_scaled <- predict(preProc, Testknn)
# 3. 寻找最佳K值
# 调整概率值,使其反映正确的类别概率
knn_prob_adjusted <- ifelse(knn_pred == "1", knn_prob, 1 - knn_prob)
# 5. 模型评估
# 计算准确率
accuracy <- mean(knn_pred == Test$结局)
# 构建混淆矩阵
conf_matrix <- confusionMatrix(knn_pred, Test$结局, positive = "1")
# 计算AUC值
roc_result <- roc(as.numeric(Test$结局), as.numeric(knn_prob_adjusted))
auc_value <- auc(roc_result)
# 提取性能指标
sensitivity <- conf_matrix$byClass["Sensitivity"]
specificity <- conf_matrix$byClass["Specificity"]
precision <- conf_matrix$byClass["Precision"]
recall <- conf_matrix$byClass["Recall"]
f1_score <- conf_matrix$byClass["F1"]
# 6. 可视化
# 绘制ROC曲线
jpeg("Results-knn/ROC_curve.jpg", width = 800, height = 600)
plot(roc_result,
print.auc = TRUE,
auc.polygon = TRUE,
grid = c(0.1, 0.2),
grid.col = c('green', 'red'),
max.auc.polygon = TRUE,
auc.polygon.col = 'steelblue',
main = "KNN模型ROC曲线")
dev.off()
pdf("Results-knn/ROC_curve.pdf", width = 8, height = 6)
plot(roc_result,
print.auc = TRUE,
auc.polygon = TRUE,
grid = c(0.1, 0.2),
grid.col = c('green', 'red'),
max.auc.polygon = TRUE,
auc.polygon.col = 'steelblue',
main = "KNN模型ROC曲线")
dev.off()
# 绘制K值选择图
jpeg("Results-knn/k_selection.jpg", width = 800, height = 600)
plot(knn_model, main = "K值选择与模型准确率")
dev.off()
pdf("Results-knn/k_selection.pdf", width = 8, height = 6)
plot(knn_model, main = "K值选择与模型准确率")
dev.off()
# 7. 保存结果
# 保存预测结果
results_table <- data.frame(
实际值 = Test$结局,
预测类别 = knn_pred,
预测概率 = knn_prob_adjusted
)
write_xlsx(results_table, "Results-knn/predictions.xlsx")
# 保存模型性能指标
# 8. 创建Word报告
doc <- read_docx()
doc <- body_add_par(doc, "KNN模型分析报告", style = "heading 1")
doc <- body_add_par(doc, paste0("分析日期: ", Sys.Date()), style = "Normal")
doc <- body_add_par(doc, "数据概览", style = "heading 2")
doc <- body_add_par(doc, paste0("总样本量: ", nrow(data)), style = "Normal")
doc <- body_add_par(doc, paste0("训练集样本量: ", nrow(Train)), style = "Normal")
doc <- body_add_par(doc, paste0("测试集样本量: ", nrow(Test)), style = "Normal")
doc <- body_add_par(doc, paste0("最佳K值: ", best_k), style = "Normal")
doc <- body_add_par(doc, "模型性能指标", style = "heading 2")
doc <- body_add_flextable(doc, flextable(performance_table))
doc <- body_add_par(doc, "混淆矩阵", style = "heading 2")
confusion_flextable <- flextable(confusion_matrix_table)
doc <- body_add_flextable(doc, confusion_flextable)
doc <- body_add_par(doc, "ROC曲线", style = "heading 2")
doc <- body_add_img(doc, "Results-knn/ROC_curve.jpg", width = 6, height = 5)
doc <- body_add_par(doc, "K值选择", style = "heading 2")
doc <- body_add_img(doc, "Results-knn/k_selection.jpg", width = 6, height = 5)
doc <- body_add_par(doc, "结论", style = "heading 2")
doc <- body_add_par(doc, paste0(
"KNN模型在测试集上表现",
ifelse(auc_value > 0.7, "良好", "一般"),
",AUC值为", round(auc_value, 3),
"。模型准确率为", round(accuracy, 3),
"。最佳K值为", best_k, "。"
), style = "Normal")
print(doc, target = "Results-knn/KNN分析报告.docx")
# 9. 保存工作空间
save.image("Results-knn/KNN分析.RData")
cat("分析完成!所有结果已保存到 Results-knn 文件夹中。")
- 环境初始化与数据准备:设置工作目录、清理环境,并创建名为"Results-knn"的结果文件夹;随后读取Excel格式的示例数据(如"示例数据.xlsx"),将分类变量(如肥胖程度、教育水平、血型等)转换为因子类型,并通过分层抽样将数据划分为训练集(80%)和测试集(20%),保存为Excel文件。
- 模型训练与优化:提取特征(如指标1-6),对数据进行标准化处理(中心化和缩放),并使用交叉验证(10折)寻找最佳K值;基于最佳K值训练KNN模型,并进行预测,同时调整概率值以反映正确的类别概率。
- 模型评估与可视化:计算准确率、生成混淆矩阵(导出灵敏度、特异度、精确率等指标),绘制ROC曲线并计算AUC值以评估分类性能;同时绘制K值选择图展示不同K值下的模型准确率变化,所有图表保存为JPG和PDF格式。
- 结果保存与报告生成:将预测结果、性能指标和混淆矩阵导出为Excel文件;自动化创建Word报告,整合数据概览、模型性能指标、可视化图表和结论性分析,并提供中文字体支持;最终保存工作空间图像到指定文件夹。
- pacman:简化包的安装和加载管理,确保依赖包就绪,避免手动检查。
- readxl:读取Excel格式的数据文件(如"示例数据.xlsx"),实现数据导入到R环境。
- writexl:将结果数据(如训练集、测试集、预测结果和性能指标)导出为Excel文件,便于后续查阅。
- caret:提供机器学习流程工具,如数据预处理(标准化)、交叉验证设置(trainControl)和模型训练(train),用于优化K值选择。
- class:核心KNN算法包,提供knn函数进行模型预测,并支持概率计算。
- pROC:绘制ROC曲线并计算AUC值,通过roc和auc函数评估模型区分能力。
- officer 和 flextable:生成和格式化Word报告,如添加标题、段落、图片和表格(通过body_add_par、body_add_img等函数),提升报告可读性。
- showtext:设置中文字体支持,确保图表和报告中的中文标签正确渲染。
该代码适用于需要快速构建简单且可解释的分类模型的场景,例如在医疗研究中预测疾病结局(如基于指标变量)、教育领域分析学生表现,或商业中识别客户行为模式。自动化流程提高了分析的可重复性和效率,适合快速生成学术论文、实践报告或教学演示材料,通过可视化输出(如ROC曲线和K值选择图)帮助用户理解模型性能并优化参数选择。KNN模型尤其适合处理中小规模数据集,且无需复杂参数假设,为决策制定或探索性分析提供基础工具。
医学统计数据分析分享交流SPSS、R语言、Python、ArcGis、Geoda、GraphPad、数据分析图表制作等心得。承接数据分析,论文返修,医学统计,机器学习,生存分析,空间分析,问卷分析业务。若有投稿和数据分析代做需求,可以直接联系我,谢谢!
“医学统计数据分析”公众号右下角;
找到“联系作者”,
可加我微信,邀请入粉丝群!
有临床流行病学数据分析
如(t检验、方差分析、χ2检验、logistic回归)、
(重复测量方差分析与配对T检验、ROC曲线)、
(非参数检验、生存分析、样本含量估计)、
(筛检试验:灵敏度、特异度、约登指数等计算)、
(绘制柱状图、散点图、小提琴图、列线图等)、
机器学习、深度学习、生存分析
等需求的同仁们,加入【临床】粉丝群。
疾控,公卫岗位的同仁,可以加一下【公卫】粉丝群,分享生态学研究、空间分析、时间序列、监测数据分析、时空面板技巧等工作科研自动化内容。
有实验室数据分析需求的同仁们,可以加入【生信】粉丝群,交流NCBI(基因序列)、UniProt(蛋白质)、KEGG(通路)、GEO(公共数据集)等公共数据库、基因组学转录组学蛋白组学代谢组学表型组学等数据分析和可视化内容。
或者可扫码直接加微信进群!!!
精品视频课程-“医学统计数据分析”视频号付费合集
在“医学统计数据分析”视频号-付费合集兑换相应课程后,获取课程理论课PPT、代码、基础数据等相关资料,请大家在【医学统计数据分析】公众号右下角,找到“联系作者”,加我微信后打包发送。感谢您的支持!!
【二分类因变量机器学习】图文教程
往期推荐:【监测预警自动化】系列教程
往期推荐:样本含量估计(样本量计算与功效分析)
往期推荐:SPSS、R语言、Python等临床数据分析专题
往期推荐:科研图表绘制专题
往期推荐:重复测量数据分析专题
往期推荐:生信分析、基因测序数据、实验室数据专题
往期推荐:生存分析及机器学习
往期推荐:时间序列分析
往期推荐:地统计分析-GIS、地图、相关、聚类、回归
往期推荐:科研自动化探究
往期推荐:趣味阅读
统计评书系列

