尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

红酒数据集分析实战:Spearman相关、主成分回归与KNN分类

发布时间:2026/9/27 3:37:36

资讯中心
01
ARTICLE

红酒数据集分析实战:Spearman相关、主成分回归与KNN分类

红酒数据集分析实战:Spearman相关、主成分回归与KNN分类
简介这份数据分析大作业资料围绕红酒数据集展开面向高校数据科学、统计学课程的作业实践者帮助读者完成从数据清洗到建模的完整分析流程。资源包内含1个docx文档约202KB以文字与代码截图形式呈现分析全过程。内容涵盖红酒11项物理属性与评分的关联性分析通过相关性筛选出挥发性酸度、硫酸盐、酒精等关键变量并建立多元线性回归模型R方为0.6589进一步采用主成分回归提取前五个主成分给出响应变量与原变量的系数转换过程同时使用KNN完成红酒的简单分类。读者可从中获取完整的分析思路、R语言与Python代码片段、变量筛选依据及模型评估方法适合作为课程作业参考或数据分析入门练手项目。目前已有4264人学习下载。1. 一份红酒数据集作业为什么值得你花时间拆开看如果你手头正好有一份数据分析大作业选题是红酒数据集要求里写着“相关性分析 回归 分类”那你大概率正卡在几个具体问题上11 个理化属性到底该留哪几个、R 方只有 0.65 算不算翻车、KNN 分类准确率上不去是不是代码写错了。这份资源就是围绕 UCI 红酒数据集展开的一套完整分析流程从 Python 转格式、R 做 Spearman 相关性、多元线性回归、主成分回归一路做到 KNN 分类最后还落到了“怎么提高红酒评分”的业务解释上。它适合正在做课程设计的学生也适合想拿一份小数据集练手回归与分类衔接的从业者。下面我按自己复现这套流程的顺序把参数、代码和踩过的坑一条条拆开讲。2. 数据准备与相关性分析11 个属性怎么砍到 8 个2.1 先搞清楚这 11 个属性分别是什么红酒数据集的每一行代表一款酒前 11 列是理化指标第 12 列是专家感官评分范围 0 到 10。原始文件是 csv作业里第一步用 Python 把它转成 xlsx方便后面 R 的 readxl 直接读。这一步看着多余但实际做作业时很有用——xlsx 能保留列名和 sheet 结构R 里read_excel指定sheet1和col_namesT就能干净地读进来不用再处理编码问题。11 个属性按顺序是非挥发性酸度、挥发性酸度、柠檬酸、残糖、氯化物、游离二氧化硫、总二氧化硫、密度、pH 值、硫酸盐、酒精。评分分布集中在 5 分和 6 分3 分和 8 分是极少数。这个分布特征很关键后面 KNN 分类准确率上不去根子就在这里。用 Python 转格式的常见写法是这样import pandas as pd # 读原始 csv注意分隔符UCI 红酒数据一般是分号 df pd.read_csv(winequality-red.csv, sep;) # 写出 xlsxsheet 名保持默认方便 R 端 read_excel 按 sheet1 读取 df.to_excel(redwine.xlsx, indexFalse, sheet_nameSheet1) # 快速看一眼评分分布确认 5、6 分占大头 print(df[quality].value_counts().sort_index())逻辑说明sep;是 UCI 红酒数据的标准分隔符如果你拿到的文件是逗号分隔这里要改成sep,否则整行会被当成一列。indexFalse避免把行号写进 xlsx 多出一列R 端读进来会多一个无意义变量。参数上sheet_name建议显式写不写默认是 Sheet1但显式写以后换文件不容易出错。2.2 Spearman 相关性分析为什么不用 Pearson作业里用的是cor(df, method spearman)不是默认的 Pearson。原因在于评分是离散的等级变量3 到 8 这种整数评分不满足 Pearson 要求的连续正态假设Spearman 基于秩次对单调关系更稳健。这一步的 R 代码install.packages(readxl) library(readxl) # 读取 xlsxcol_namesT 表示第一行是列名 df - read_excel(redwine.xlsx, sheet 1, col_names TRUE) # Spearman 相关性矩阵对等级评分更合适 cor_matrix - cor(df, method spearman) print(round(cor_matrix, 3))逻辑说明cor函数对数据框整体计算会得到 12×12 的矩阵最后一列或最后一行就是各属性与评分的相关系数。参数method可选 pearson、spearman、kendall这里选 spearman 是因为评分是序数。跑完看结果x4 残糖、x6 游离二氧化硫、x9 pH 值与评分相关性低可以砍掉x2 挥发性酸度、x10 硫酸盐、x11 酒精相关性较高保留。这里有个容易忽略的点变量之间本身也有相关性。pH 与非挥发性酸相关很高酒精与密度也有联系。这意味着直接拿全部变量做回归会引入多重共线性后面主成分回归就是为了处理这个问题。降维到 8 个变量去掉 x4、x6、x9是第一步但 8 个变量之间仍然不独立。提示相关性矩阵不要只看和评分那一列变量之间的高相关对后面回归系数符号的稳定性影响很大建议把整个矩阵扫一遍再决定去留。3. 多元线性回归与主成分回归R 方 0.65 之后怎么办3.1 全变量回归为什么部分参数通不过检验去掉低相关变量后用剩余 8 个变量做回归# q 是评分x1 到 x11 对应 11 个属性这里用去掉 x4、x6、x9 后的变量 lm_sol - lm(q ~ x1 x2 x3 x5 x7 x8 x10 x11, data df) summary(lm_sol)逻辑说明lm是 R 的线性模型函数公式q ~ x1 ...表示评分对 8 个属性回归。summary输出里重点看三块Coefficients 表的 Pr(|t|) 是每个系数的显著性Multiple R-squared 是拟合优度F-statistic 是整体显著性。作业里发现部分参数没通过检验这是多重共线性的典型症状——变量之间互相解释导致单个系数估计不稳定、标准误变大、t 值变小。遇到这种情况常见做法有两种一是手动挑相关性最高的三个变量做精简回归二是上主成分回归。作业两条路都走了。3.2 三变量精简回归R 方 0.6589 的取舍选 x2 挥发性酸度、x10 硫酸盐、x11 酒精三个变量lm_sol2 - lm(q ~ x2 x10 x11, data df) summary(lm_sol2) # 用一组留出的数据做预测x20.31, x100.66, x1111 new_data - data.frame(x2 0.31, x10 0.66, x11 11) lm_conf - predict(lm_sol2, new_data, interval confidence) lm_pred - predict(lm_sol2, new_data, interval prediction) print(lm_conf) print(lm_pred)逻辑说明predict的interval参数有两个取值confidence 给的是回归线均值的置信区间prediction 给的是单个新观测的预测区间后者一定比前者宽因为多了个体误差。作业里这组数据实际评分是 6预测结果比较接近。R 方 0.6589 意味着三个变量解释了约 66% 的评分变异剩下 34% 来自未纳入的变量和噪声。这个值在感官评分预测里不算低因为感官评分本身主观性就大。参数上要注意new_data的列名必须和模型里的变量名完全一致写成x2、x10、x11不能写成X2或volatile_acidity否则predict会报“变量长度不一致”或找不到变量的错。3.3 主成分回归把 11 个变量压成 5 个主成分主成分回归的思路是先做 PCA 降维再对主成分做回归最后把系数转换回原始变量。R 代码# 读取全部 11 个属性range 指定 A1:K1559 wine - read_excel(redwine.xlsx, sheet 1, col_names TRUE, range A1:K1559) # princomp 做主成分corTRUE 表示用相关阵而非协方差阵 wine_pr - princomp(wine, cor TRUE) summary(wine_pr, loadings TRUE) # 提取前五个主成分得分 pre - predict(wine_pr) z1 - pre[, 1]; z2 - pre[, 2]; z3 - pre[, 3]; z4 - pre[, 4]; z5 - pre[, 5] # 评分对五个主成分回归 redd - data.frame(q df[12], z1, z2, z3, z4, z5) lm_solp - lm(q ~ z1 z2 z3 z4 z5, data redd) summary(lm_solp)逻辑说明princomp的corTRUE很关键因为 11 个属性量纲差异大——密度在 1 附近总二氧化硫在几十酒精在 10 左右。用相关阵等于先标准化再 PCA避免量纲大的变量主导主成分。summary的 loadings 部分给出各主成分的载荷也就是每个原始变量对主成分的贡献。取前五个主成分是因为它们累计解释了大部分方差具体看 Cumulative Proportion 那一行。系数转换回原始变量这一步是主成分回归最容易翻车的地方XX - cor(wine) A - eigen(XX)$vectors beta - coef(lm_solp) # 原始变量的均值和标准差从数据里算出来 X_bar - colMeans(wine) X_sd - apply(wine, 2, sd) # 主成分系数转原始变量系数 coef_raw - (beta[2]*A[,1] beta[3]*A[,2] beta[4]*A[,3] beta[5]*A[,4]) / X_sd beta0 - beta[1] - sum(X_bar * coef_raw) print(c(beta0, coef_raw))逻辑说明eigen(XX)$vectors是相关阵的特征向量对应 princomp 的载荷方向。beta[2]到beta[5]是评分对前四个主成分的回归系数beta[1] 是截距。除以X_sd是因为 princomp 内部做了标准化转换回原始尺度要还原。beta0的修正项sum(X_bar * coef_raw)是把数据中心化带来的截距偏移补回去。作业里代入一组主成分值得到的结果和实际 6 分有一定偏差这是主成分回归用降维换稳定性的代价。注意range A1:K1559里的行数要和你实际数据行数一致写多了会读进空行导致 NA写少了会丢样本。建议先用nrow确认行数再填。4. KNN 分类为什么准确率上不去怎么排查4.1 KNN 三要素与这份作业的选择KNN 的三个要素是 k 值、距离度量、分类决策规则。作业里选 2-挥发性酸度、5-氯化物、7-总二氧化硫、10-硫酸盐、11-酒精五项作为距离度量维度k 取 20决策规则是多数表决。代码用 openpyxl 读 xlsx手写距离计算和分类import openpyxl def read_excel(input_file_name, objects): 从 xlsx 读取指定列objects 是输出列表 workbook openpyxl.load_workbook(input_file_name) table1 workbook[Sheet1] rows table1.max_row cols table1.max_column for row in range(1, rows): obj [] for col in range(cols): # 取第 2、5、7、10、11 列属性加第 12 列评分 if col in (1, 4, 6, 9, 10, 11): data table1.cell(row 1, col 1).value obj.append(data) objects.append(obj) return objects def knndis(nowa, objects): 计算 nowa 到所有样本的欧氏距离 distances [] for i in range(len(objects)): distance 0 for j in range(5): distance (objects[i][j] - nowa[j]) ** 2 distances.append(distance ** 0.5) return distances def classify(distances, objects): 取最近 30 个点的评分做多数表决 d {} for i in range(30): idx distances.index(min(distances)) item objects[idx][5] d[item] d.get(item, 0) 1 distances[idx] 100 # 把已选点推远避免重复选 # 输出出现次数最多的评分 return max(d, keyd.get)逻辑说明read_excel里col in (1,4,6,9,10,11)对应第 2、5、7、10、11 个属性和第 12 列评分因为 openpyxl 的 cell 索引从 1 开始而 col 从 0 开始所以判断用 0 基、取值用col1。knndis算的是五维欧氏距离没有做标准化——这是准确率上不去的一个隐藏原因后面排查会讲。classify里distances[idx] 100是把已选最近点推远防止同一个点被重复计数这个技巧比删除列表元素更省事。4.2 准确率不高的三个真实原因作业里自己写了“准确度并不是很高”并给了两个原因评分 5、6 占绝大多数属性和评分相关性不高。这两个都对但还有第三个常被忽略的原因——距离计算前没做标准化。排查记录如下现象KNN 分类准确率明显低于预期多数样本被预测成 5 或 6。原因评分分布极度不平衡5 分和 6 分占了绝大多数多数表决天然偏向多数类。解决要么对少数类过采样要么改用距离加权投票让近的点权重更大。现象不同属性对距离的贡献差异巨大。原因总二氧化硫数值在几十酒精在 10 左右氯化物在 0.1 以下直接算欧氏距离时大数值属性主导了距离。解决距离计算前对每个属性做 z-score 标准化(x - mean) / std。现象k 取 20 时准确率反而比 k 取小值低。原因k 太大时邻域覆盖了太远的点类别边界被模糊。解决用交叉验证扫一遍 k 值常见做法是取 3 到 15 之间试。现象只看最近一个点的评分时准确率明显更高。原因最近点受多数类影响最小但方差大。解决这是 k1 的特例可以作为准确率上限的参考但不建议直接用作最终模型。提示KNN 对量纲敏感是血泪经验任何基于距离的算法KNN、K-means、层次聚类上之前都先标准化这一步省不得。5. 从系数到业务结论怎么把回归结果讲成一句人话5.1 回归系数怎么读三变量回归的结果是p -1.22130*x2 0.67898*x10 0.30920*x11 2.61104。读法是挥发性酸度每增加 1 个单位评分平均下降约 1.22 分硫酸盐每增加 1 个单位评分平均上升约 0.68 分酒精每增加 1 个单位评分平均上升约 0.31 分。截距 2.61 是三个变量都为 0 时的理论评分实际中不会出现只作为方程的一部分。这个结论和酿酒常识能对上挥发性酸度高会让酒闻起来像醋或洗甲水破坏平衡性硫酸盐防止氧化、保持新鲜口感还参与提取色素和风味酒精直接影响口感和酒体。作业最后落到“减少挥发性酸、增加硫酸盐和酒精有助于提高评分”这是把统计结果翻译成业务语言的正确姿势。5.2 主成分回归的系数怎么验证主成分回归转换回原始变量后系数符号应该和三变量回归一致——挥发性酸度为负硫酸盐和酒精为正。如果符号反了大概率是特征向量方向或标准化还原那一步写错了。验证方法很简单把转换后的系数代回几个样本算出的预测值和直接用lm_solp对主成分的预测值应该一致在数值误差范围内。# 验证用原始变量系数算预测值和主成分模型预测值对比 sample_idx - 1 x_raw - as.numeric(wine[sample_idx, ]) pred_raw - beta0 sum(coef_raw * x_raw) pred_pca - predict(lm_solp, newdata data.frame(z1z1[sample_idx], z2z2[sample_idx], z3z3[sample_idx], z4z4[sample_idx], z5z5[sample_idx])) print(c(pred_raw, pred_pca))逻辑说明两个值应该接近差异来自数值精度和主成分只取了前五个的截断误差。如果差很多检查coef_raw的除法是不是用了X_sd而不是X_sd^2以及beta0的修正项有没有漏掉。5.3 一份作业的完整复现检查清单步骤关键参数常见错误验证方式csv 转 xlsxsep 分隔符、indexFalse分隔符写错导致单列打印列数应为 12Spearman 相关methodspearman用默认 Pearson评分列相关系数符号合理全变量回归公式变量名与列名一致变量名大小写不一致summary 无报错三变量回归new_data 列名匹配列名写成中文predict 返回三列区间主成分回归corTRUE、range 行数行数写多读进 NA累计方差比例合理系数转换除以 X_sd 而非方差截距修正漏项代回样本预测一致KNN标准化、k 值未标准化、k 过大交叉验证选 k这张表我每次复现类似流程都会过一遍尤其是主成分系数转换和 KNN 标准化这两步翻车概率最高。5.4 一个具体技巧用 k1 的准确率给 KNN 定上限KNN 调参时与其盲目扫 k不如先跑 k1 看准确率。k1 时预测的就是最近邻的评分没有多数表决的平滑准确率通常最高但方差大。这个值可以作为你调参的上限参考——如果 k1 的准确率都只有 60%那说明特征选择或标准化有问题调 k 也救不回来。我一般会先跑 k1、3、5、7、9、11、15、20 一组画出准确率随 k 的变化曲线选曲线开始明显下降前的那个 k。从那以后我每次做基于距离的分类都强制先跑一遍 k1 和标准化前后的对比确认特征尺度处理干净了再往下调。希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。