
简介这份资源面向R语言数据分析初学者与统计建模爱好者围绕ggplot2自带的diamonds数据集展开钻石价格分析帮助读者掌握回归分析与机器学习在真实数据上的应用。压缩包内共1个docx文档约2.4MB内容涵盖数据探索、缺失值与重复值检查、异常值剔除、描述性统计、直方图与箱线图可视化以及多元线性回归建模与价格预测的完整流程。文档结合54000余颗钻石的克拉重量、切工、颜色、净度等变量逐步演示如何筛选影响价格的关键因素并解读模型结果适合作为课程作业、案例复现或数据分析入门的参考材料。目前已有283人学习下载读者可借此熟悉R语言的数据清洗、可视化与建模思路理解钻石价格背后的决定因素与预测方法。1. 钻石价格分析-基于R语言从散点图到定价因子的第一公里手里有一份钻石数据集54000 行、10 个字段价格从 326 美元到 18823 美元不等。第一次拿到它的人八成会先画一张 carat 对 price 的散点图然后盯着那条指数曲线发愣——明明克拉数只差 0.1价格却能差出好几千美元。这就是钻石定价的迷人之处它从来不是单变量游戏而是克拉、切工、颜色、净度四个 C 加上一堆几何尺寸的联合博弈。用 R 语言做钻石价格分析核心目标就一个把「哪些因素在推高价格、各推高多少、有没有非线性拐点」这件事从直觉变成可量化、可复现的模型输出。适合已经装好 R 和 RStudio、会写read.csv但还没系统跑过完整回归流程的人也适合想拿一个干净数据集练手 ggplot2 和回归建模的从业者。这一章不急着建模先把数据摸清楚把「价格到底长什么样」这件事看透。2. 数据读入与探索性分析用 ggplot2 把价格分布拆开看2.1 读数据与字段类型确认钻石数据集常见来源是 ggplot2 包自带的diamonds也可以从外部 CSV 读入。我一般先用str()和summary()过一遍确认数值型和因子型有没有被误读。# 方式一直接用 ggplot2 内置数据集 library(ggplot2) data(diamonds) # 方式二从 CSV 读入假设文件在当前工作目录 # diamonds - read.csv(diamonds.csv, stringsAsFactors TRUE) # 查看结构与摘要 str(diamonds) summary(diamonds) # 确认因子水平顺序 levels(diamonds$cut) levels(diamonds$color) levels(diamonds$clarity)str()会告诉你cut、color、clarity是 Factorprice是 int。这里有个容易翻车的点color从 D 到 JD 最好clarity从 I1 到 IFIF 最好。但 R 默认按字母顺序排因子水平建模时参考基准会乱。我一般手动重排让「最差」或「最好」当基准后面解释系数才不拧巴。# 重排因子水平让有序关系符合业务含义 diamonds$cut - factor(diamonds$cut, levels c(Fair, Good, Very Good, Premium, Ideal), ordered FALSE) diamonds$color - factor(diamonds$color, levels c(J, I, H, G, F, E, D), ordered FALSE) diamonds$clarity - factor(diamonds$clarity, levels c(I1, SI2, SI1, VS2, VS1, VVS2, VVS1, IF), ordered FALSE)参数说明levels里第一个元素会成为回归模型的参考基准。把J放第一个意味着后面 color 的系数都是「相对于 J 色」的价格变化。这个选择直接影响你读系数的方向别随手抄别人的顺序。2.2 价格分布与对数变换的判断钻石价格是典型的右偏分布直接拿原始价格做线性回归残差会严重违背正态假设。先画直方图和密度曲线确认偏度。library(ggplot2) # 原始价格分布 p1 - ggplot(diamonds, aes(x price)) geom_histogram(bins 60, fill steelblue, color white) labs(title 钻石价格原始分布, x 价格(美元), y 频数) # 对数价格分布 p2 - ggplot(diamonds, aes(x log(price))) geom_histogram(bins 60, fill darkorange, color white) labs(title 对数价格分布, x log(价格), y 频数) # 并排查看需要 patchwork 或 gridExtra library(patchwork) p1 p2逻辑说明原始价格直方图右侧拖尾很长log 变换后接近对称。后续建模我一般用log(price)当因变量这样残差更稳系数的解释也变成「百分比变化」——在定价场景里比绝对美元数更直观。注意如果业务方要的是「预测具体美元价格」建模完记得用exp()还原并检查还原后的预测误差是否可接受。2.3 克拉与价格的散点关系ggplot(diamonds, aes(x carat, y price)) geom_point(alpha 0.1, color steelblue) geom_smooth(method lm, formula y ~ poly(x, 3), color red) labs(title 克拉与价格的非线性关系, x 克拉, y 价格(美元))这张图会告诉你两件事第一价格随克拉增长明显不是直线三次多项式拟合比线性好得多第二在 1.0、1.5、2.0 克拉附近有垂直的「价格墙」——整数克拉的钻石溢价明显。这个现象在建模时要么用分段项要么把克拉取整当额外特征。我一般先跑一版只用carat的模型看残差在哪些克拉区间系统性偏高再决定要不要加carat的分段或交互项。3. 回归模型搭建从线性到交互项的逐步推进3.1 基准线性模型与系数解读先跑一个最朴素的模型log(price)对carat加三个 C 类因子。# 基准模型 fit_base - lm(log(price) ~ carat cut color clarity, data diamonds) summary(fit_base) # 查看系数 coef(fit_base)输出里你会看到carat系数大约在 1.8 到 2.0 之间意思是克拉每增加 1log 价格平均增加约 1.9换算成百分比就是价格乘以exp(1.9) ≈ 6.7倍。cut的系数可能让你意外Ideal 切的系数未必比 Fair 高很多甚至可能不显著。这不是数据错了而是因为carat和cut存在共线性——大克拉钻石往往切工评级偏低。基准模型的作用是给你一个「控制其他变量后」的净效应但单看它容易误判切工不值钱。3.2 加入交互项与多项式项克拉和切工、克拉和净度之间都有交互效应。大克拉钻石对切工更敏感小克拉钻石切工差异被价格基数掩盖。我一般加carat:cut和carat:clarity两组交互。# 交互模型 fit_inter - lm(log(price) ~ carat * cut carat * clarity color, data diamonds) summary(fit_inter) # 比较两个模型的拟合优度 anova(fit_base, fit_inter)参数说明carat * cut在 R 公式里等价于carat cut carat:cut会自动展开主效应和交互项。anova()做 F 检验如果 p 值小于 0.05说明交互项整体显著值得保留。但交互项一多系数解释就变得麻烦——某个 cut 水平的系数不再是固定值而是随 carat 变化的斜率。我一般会在报告里固定几个 carat 值比如 0.5、1.0、1.5分别算预测值用表格呈现而不是硬解释交互系数。3.3 模型诊断残差图与影响点# 残差诊断四联图 par(mfrow c(2, 2)) plot(fit_inter) # 找高杠杆点 hat_values - hatvalues(fit_inter) high_leverage - which(hat_values 2 * mean(hat_values)) length(high_leverage) # 找大残差 std_resid - rstandard(fit_inter) outliers - which(abs(std_resid) 3) length(outliers)逻辑说明残差对拟合值图如果出现漏斗形说明异方差还在考虑对 carat 也做变换或加权重。QQ 图尾部偏离说明有极端价格样本。高杠杆点不一定是坏事但数量太多说明模型被少数样本主导。我一般会记录这些点的索引跑一版剔除后的模型对比系数变化如果核心系数方向不变就在报告里注明「已检查影响点结论稳健」。4. 避坑与排查钻石价格建模里最容易翻车的五件事4.1 现象cut 系数为负Ideal 比 Fair 还便宜原因carat和cut强共线。大克拉钻石切工评级普遍偏低模型把克拉的价格效应部分错误分配给了 cut。解决不要单独解释 cut 主效应看交互项或在固定 carat 下比较预测值。也可以先做carat分箱在每个箱内看 cut 的价格差异。4.2 现象log(price) 还原后预测值严重偏低原因exp(mean(log(y)))不等于mean(y)对数变换后直接取 exp 会低估。解决用 smearing 修正exp(pred) * mean(exp(resid))或者干脆在原始尺度上评估误差。4.3 现象因子水平顺序改了系数全变但模型拟合不变原因参考基准变了系数含义变了但模型整体拟合优度不变。解决这是正常现象报告里写清楚基准是谁。我一般把「最差」当基准这样系数都是正数读起来顺。4.4 现象加了交互项后 R² 涨了但预测误差没降原因交互项在样本内拟合好样本外可能过拟合。解决用交叉验证比较caret或rsample做 5 折看 RMSE 而不是只看 R²。4.5 现象克拉整数位置的价格墙没被模型捕捉原因carat当连续变量处理1.0 和 0.99 的差异被平滑掉了。解决加一个carat_round round(carat, 1)的因子或者用样条splines::ns(carat, df 5)让模型自己学拐点。5. 用交叉验证和分段预测把模型落到定价场景5.1 交叉验证选模型library(caret) set.seed(42) # 定义训练控制 train_control - trainControl(method cv, number 5) # 训练交互模型 fit_cv - train(log(price) ~ carat * cut carat * clarity color, data diamonds, method lm, trControl train_control) print(fit_cv) fit_cv$results$RMSE逻辑说明trainControl指定 5 折交叉验证train会自动跑 5 次训练和验证。输出的 RMSE 是 log 价格尺度上的要跟基准模型比。我一般会同时跑fit_base和fit_inter的 CV如果交互模型 RMSE 低 5% 以上才保留。5.2 分段预测表给业务方看的定价参考# 构造新数据固定 color G, clarity VS2变化 carat 和 cut new_data - expand.grid( carat c(0.5, 1.0, 1.5, 2.0), cut levels(diamonds$cut), color G, clarity VS2 ) # 预测 log 价格并还原 new_data$pred_log - predict(fit_inter, newdata new_data) new_data$pred_price - exp(new_data$pred_log) # 整理成表 library(dplyr) new_data %% select(carat, cut, pred_price) %% arrange(carat, cut) %% tidyr::pivot_wider(names_from cut, values_from pred_price)参数说明expand.grid生成所有组合predict用训练好的模型算 log 价格exp还原。注意这里没做 smearing 修正如果要更准加mean(exp(resid(fit_inter)))乘上去。输出表格可以直接给业务方看同样 1 克拉 G 色 VS2Ideal 切比 Fair 切贵多少一目了然。5.3 一个我常用的技巧用broom批量整理模型输出library(broom) # 整理系数表 tidy_fit - tidy(fit_inter, conf.int TRUE) tidy_fit # 整理模型整体指标 glance_fit - glance(fit_inter) glance_fittidy()把系数、标准误、p 值、置信区间整理成 data.frame方便导出 CSV 或直接进 R Markdown 表格。glance()给 AIC、BIC、R²、调整 R²。我习惯把多个模型的glance()用bind_rows()拼起来一眼看哪个模型综合最优。这个习惯帮我省了很多来回翻summary()的时间。5.4 最后说一个我踩过的坑早期我做钻石价格分析时直接拿原始 price 跑线性回归R² 只有 0.85 左右残差图惨不忍睹。后来换成 log(price)R² 跳到 0.98但我在报告里写「模型解释了 98% 的价格变异」被业务方追问「那为什么预测 1 克拉钻石误差还有 800 美元」。血泪经验R² 高不代表预测准尤其在对数尺度上。后来我养成习惯所有模型评估都回到原始美元尺度算 MAE 和 RMSE再决定要不要上线。这个习惯希望帮到你。本文还有配套的精品资源点击获取