先描述再推断:建模前要看清数据

很多人一上来就跑模型,结果被一堆系数和警告淹没。正确顺序是:先用描述统计把数据看清楚,再谈建模。R 的好处是,这些探索性操作几乎都是一行命令,很快就能对数据形状建立直觉。

# 用内置的 mtcars 数据:32 款车型的油耗与性能
data(mtcars)

summary(mtcars$mpg)      # 油耗的最小/中位/均值/最大
table(mtcars$cyl)        # 气缸数有几类、各多少辆
cor(mtcars[, c("mpg", "disp", "hp", "wt")])  # 相关系数矩阵

先问三个问题:目标变量(这里是油耗 mpg)大概什么范围?有没有明显的极端值?哪些自变量看起来和它相关?把这些先看明白,后面建模时你才知道哪个系数是"理所当然"、哪个是"出乎意料需要解释"。

建模不是跑一行 lm 就结束。从描述统计到拟合、再到残差诊断和可视化,是一条必须走完的闭环,缺哪一环,结论都站不稳。
本文核心知识点
  • lm用 y ~ x 公式拟合线性回归,summary 看系数与显著性。
  • R²/p值R² 衡量解释力,p 值判断系数是否显著,别只看 R²。
  • 残差残差应随机散布、无规律,否则模型假设不成立。
  • kmeans无监督聚类,按 k 把样本自动分成若干簇,再画图验证。
R 统计建模配图:蓝绿渐变背景上离散圆点聚成数簇,中央一条从左下向右上上升的发光拟合斜线穿过点群,外围椭圆置信圈,右下整齐柱状方块组,背景网格坐标线
回归画一条穿过数据的线,聚类把一团点自然分成几堆——一 supervised 一无监督,正好互补。

线性回归 lm:公式接口怎么写

R 最优雅的设计之一是公式接口:y ~ x1 + x2 直接念出来就是"用 x1 和 x2 解释 y"。把它交给 lm(),就得到一个线性回归模型对象,后续所有诊断都围着这个对象转。

data(mtcars)

# 用车重 wt 和马力 hp 预测油耗 mpg
fit <- lm(mpg ~ wt + hp, data = mtcars)

# 看拟合出的系数
coef(fit)
# (Intercept)          wt          hp
#  37.227      -3.878      -0.031

系数怎么读?截距 37.2 是两个自变量都为 0 时的基准油耗(现实中未必有意义);wt 的系数是负的 -3.88,表示车每重一千磅,油耗平均下降约 3.9 英里每加仑——直觉上完全合理,车越重越费油。公式里用 + 连接自变量,乘 * 则还会自动加入交互项。

读懂回归输出:系数、R² 与 p 值

光看系数数字不够,要 summary() 把整张表调出来,重点看三样:系数的 p 值、残差标准误、以及 R²。

summary(fit)

# 节选关键部分:
# Coefficients:
#             Estimate Std. Error t value Pr(>|t|)
# (Intercept) 37.22755    1.59874  23.281  < 2e-16 ***
# wt          -3.87783    0.63273  -6.129  1.12e-06 ***
# hp          -0.03177    0.00903  -3.518  0.00110 **
#
# Multiple R-squared:  0.8268
指标含义怎么判断
Estimate系数估计值符号和量级是否符合业务直觉
Pr(>|t|)系数的 p 值小于 0.05 才算显著,有星号更直观
R²模型解释了多少方差越接近 1 越好,但不能脱离样本量空谈

这里 R² 约 0.83,说明车重和马力合起来解释了约 83% 的油耗差异,对一个只有两个变量的模型来说相当不错;两个系数的 p 值都远小于 0.01,说明它们对油耗的影响是统计上真实的,不是随机噪声。

残差诊断:模型假设成立吗

线性回归有几个前提假设:残差(真实值减预测值)应当均值为零、方差恒定、大致正态。lm 直接对模型对象画图就能看到诊断图。理想情况下,残差应像一团随机散开的云,没有明显的曲线或喇叭口。

par(mfrow = c(2, 2))     # 把四诊断图画在一页
plot(fit)                # 残差vs拟合、Q-Q、尺度-位置、残差vs杠杆
  • 残差 vs 拟合值:如果出现明显的曲线弯曲,说明线性假设不够,可能需要加二次项。
  • Q-Q 图:点大致贴在对角线上,说明残差近似正态;严重偏离就该警惕。
  • 尺度-位置图:点应水平随机散布;若越往右越散开(喇叭口),说明方差不齐。
  • 个别高杠杆点(Q-Q 图角落的编号点)要单独看,它是不是个别特殊样本。

诊断不是走形式:残差有规律,意味着模型漏掉了重要结构,此时再漂亮的 R² 也不能放心拿去做预测。

kmeans 聚类:无监督地把样本分组

回归需要一个明确的目标变量;但有时候你只有一堆特征,想看看"这些样本自然能分成几类"——这就是聚类。R 里最常用的是 kmeans,你先告诉它想聚成几类(k),它就迭代地把距离最近的点归到一起。

data(mtcars)
# 只用数值特征,先标准化消除量纲影响
X <- scale(mtcars[, c("mpg", "disp", "hp", "wt")])

set.seed(1)                       # 固定随机种子,结果可复现
km <- kmeans(X, centers = 3)      # 聚成 3 类

km$cluster                        # 每辆车属于哪一类
table(km$cluster)                # 每类各有多少辆车

两个要点:第一,聚类前一定要标准化,否则"马力几百"会把"车重几吨"的距离比下去,量纲大的变量主导一切;第二,k 是你自己定的,可以先用"肘部法则"看不同 k 下类内平方和的下降速度,在下降变缓的拐点附近挑 k。聚类结果是一种探索,不是标准答案——要结合业务解释每一类代表什么。

用 ggplot2 把结果画出来

模型结论不画出来就不算完成。ggplot2 的图层语法很顺手:先铺数据、再映射颜色形状、然后一层层加几何对象。下面把回归拟合线和聚类分组同一张图里呈现。

library(ggplot2)
data(mtcars)
mtcars$cluster <- factor(km$cluster)   # 聚类结果作为分组颜色

ggplot(mtcars, aes(x = wt, y = mpg, color = cluster)) +
  geom_point(size = 2) +                              # 散点,按簇着色
  geom_smooth(method = "lm", se = FALSE, color = "gray30") +  # 加回归线
  labs(x = "车重", y = "油耗(mpg)", title = "车重与油耗")

读图时一眼就能看出三件事:散点整体从左上往右下走(车重越大油耗越低)、三种颜色的簇各自扎堆、灰色回归线概括了整体趋势。图把"系数表上的几个数字"变成了肉眼可辨的结构,这正是建模最后一步可视化的价值。