数据挖掘与R语言

第12讲:对数回归与分类自变量

2026年05月08日

上讲回顾

  • 偏回归系数\(\hat{\beta}_j\) 是「控制其他变量不变」条件下,\(x_j\) 每增加 1 个单位,\(y\) 预期变化多少(ceteris paribus
  • 多重共线性:自变量高度相关时系数估计不稳定;用 VIF 诊断,VIF \(> 10\) 需处理
  • 模型选择:比较模型用 Adjusted \(R^2\) 和 AIC,不要用 \(R^2\)
  • R 操作lm(y ~ x1 + x2)vif()AIC()
  • 但是:所有这些都默认 \(y\)\(x\) 之间是线性关系如果关系不是线性的,怎么办? 这是今天的起点

本讲内容

  • Part 1:为什么需要对数变换? ——非线性关系的识别与处理思路
  • Part 2:只对 \(x\) 取对数(level-log) ——\(x\) 每增加1%,\(y\) 变化多少?
  • Part 3:只对 \(y\) 取对数(log-level) ——\(x\) 增加 1,\(y\) 变化百分之几?
  • Part 4:\(x\)\(y\) 同时取对数(log-log) ——弹性系数
  • Part 5:分类自变量——两类 ——虚拟变量的建立与解读
  • Part 6:分类自变量——三类及以上 ——参照组与多个虚拟变量
  • Part 7:你必须掌握什么? ——学习路线图

Part 1:为什么需要对数变换?

当散点图不是一条直线

线性假设的局限

复习:线性回归的前提是 \(y\)\(x\) 之间存在线性关系。

注记

散点图是诊断工具。 如果散点图呈现弯曲趋势,不要强行套线性回归——考虑对数变换。

哪些变量天然适合取对数?

适合取对数的变量(正数且跨越多个数量级):

  • 价格、收入、财富、GDP
  • 人口规模、城市面积
  • 网站访问量、用户数(倍数增长)
  • 广告效果、学习曲线(收益递减)

提示

快速判断三步法:

  1. 画散点图——是否弯曲?
  2. 变量是否都是正数?(取对数要求 \(> 0\)
  3. 变量分布是否严重右偏

满足以上任意一点,就可以考虑取对数。

对数变换的三种形式

模型 方程 系数解读 典型场景
level-log \(y = \beta_0 + \beta_1 \ln(x) + \varepsilon\) \(x\) 增加 1%,\(y\) 变化 \(\beta_1 / 100\) 个单位 广告费→销量
log-level \(\ln(y) = \beta_0 + \beta_1 x + \varepsilon\) \(x\) 增加 1,\(y\) 变化约 \(\beta_1 \times 100\%\) 经验→工资
log-log \(\ln(y) = \beta_0 + \beta_1 \ln(x) + \varepsilon\) \(x\) 增加 1%,\(y\) 变化 \(\beta_1\%\)(弹性) 价格→需求量

重要

无论哪种变换,R 中只需在 lm() 里用 log() 包裹变量。模型仍然是对系数线性的——线性假设是针对系数,不要求原始变量之间线性。

Part 2:只对 \(x\) 取对数(level-log模型)

\(x\) 每增加1%,\(y\) 变化多少?

问题背景:广告费与销量

现实规律: 广告的边际效益是递减的——第一个 100 万效果显著,第二个 100 万效果没那么好。这是对数增长,不是线性增长。

建立 level-log 模型

▶️ 查看代码
set.seed(7)
n <- 80
ad_log <- data.frame(广告费 = runif(n, 1, 200)) |>
  mutate(销量 = 10 + 25 * log(广告费) + rnorm(n, sd = 8))

ad_log |> 
  ggplot(aes(x = 广告费, y = 销量)) + 
  geom_point() + 
  labs(title = "广告费 vs 销量", x = "广告费", y = "销量")

▶️ 查看代码
ad_log |> 
  ggplot(aes(x = log(广告费), y = 销量)) + 
  geom_point() + 
  labs(title = "广告费 vs 销量", x = "广告费", y = "销量")

▶️ 查看代码
# level-log 模型:对 x(广告费)取自然对数
model_level.log <- lm(销量 ~ log(广告费), data = ad_log)
summary(model_level.log)

Call:
lm(formula = 销量 ~ log(广告费), data = ad_log)

Residuals:
    Min      1Q  Median      3Q     Max 
-15.517  -4.578   0.646   4.533  18.558 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)     8.09       4.59    1.76    0.082 .  
log(广告费)    25.61       1.02   25.10   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 7.13 on 78 degrees of freedom
Multiple R-squared:  0.89,  Adjusted R-squared:  0.888 
F-statistic:  630 on 1 and 78 DF,  p-value: <2e-16

解读 level-log 系数

根据输出,回归方程为:

\[\widehat{\text{销量}} = \hat{\beta}_0 + 24.8 \times \ln(\text{广告费})\]

\(x\) 增加 1%(即 \(\ln(x)\) 增加约 \(0.01\))时:

如何解读斜率 \(\hat{\beta}_1 = 24.8\)

\(x\) 增加 1%(即 \(\ln(x)\) 增加约 \(0.01\))时:

\[\Delta\hat{y} \approx \hat{\beta}_1 \times 0.01 = 24.8 \times 0.01 = 0.248 \text{ 万件}\]

提示

level-log 系数的解读口诀:

\(x\) 每增加 1%\(y\) 增加约 \(\hat{\beta}_1 \div 100\) 个单位

具体说: 广告费每增加 1%,销量预期增加约 0.248 万件

等价地:广告费每翻一番(+100%),销量增加约 \(24.8 \times \ln(2) \approx 17.2\) 万件。

▶️ 查看代码
# 线性模型 vs log-level 模型:哪个拟合更好?
model_linear <- lm(销量 ~ 广告费, data = ad_log)

modelsummary(list(model_linear, model_level.log),
             stars = T)
(1) (2)
+ p < 0.1, * p < 0.05, ** p < 0.01, *** p < 0.001
(Intercept) 87.136*** 8.087+
(2.558) (4.585)
广告费 0.329***
(0.022)
log(广告费) 25.605***
(1.020)
Num.Obs. 80 80
R2 0.748 0.890
R2 Adj. 0.744 0.888
AIC 611.5 545.2
BIC 618.7 552.4
Log.Lik. -302.774 -269.607
F 230.947 629.924
RMSE 10.65 7.04

Part 3:只对 \(y\) 取对数(log-level 模型)

\(x\) 增加 1,\(y\) 变化百分之几?

问题背景:工作经验与工资

现实规律: 工资随经验的增长往往是指数型的——从 0 到 5 年涨幅小,从 20 到 25 年涨幅相对大。对 \(y\) 取对数后,关系趋于线性。

建立 log-level 模型

▶️ 查看代码
set.seed(21)
n <- 100
exp_data <- data.frame(经验年数 = runif(n, 0, 30)) |>
  mutate(工资 = exp(7.5 + 0.06 * 经验年数 + rnorm(n, sd = 0.25)))

# level-log 模型:对 y(工资)取自然对数
model_log.level <- lm(log(工资) ~ 经验年数, data = exp_data)
summary(model_log.level)

Call:
lm(formula = log(工资) ~ 经验年数, data = exp_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-0.7216 -0.1556  0.0086  0.1906  0.5006 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  7.47821    0.05190   144.1   <2e-16 ***
经验年数     0.06038    0.00273    22.1   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.246 on 98 degrees of freedom
Multiple R-squared:  0.833, Adjusted R-squared:  0.832 
F-statistic:  490 on 1 and 98 DF,  p-value: <2e-16

解读 level-log 系数

回归方程为:

\[\ln(\widehat{\text{工资}}) = \hat{\beta}_0 + 0.060 \times \text{经验年数}\]

如何解读斜率 \(\hat{\beta}_1 = 0.060\)

\(x\) 增加 1 时,\(\ln(y)\) 增加 \(0.060\),因此 \(y\)百分比变化为:

\[\% \Delta y \approx \hat{\beta}_1 \times 100\% = 6.0\%\]

提示

log-level 系数的解读口诀:

\(x\) 每增加 1 个单位\(y\) 增加约 \(\hat{\beta}_1 \times 100\%\)

具体说: 工作经验每增加 1 年,工资预期增加约 6.0%

这正是经济学中「Mincer 工资方程」的标准形式。

注记

大系数时用精确公式: \((e^{\hat{\beta}_1} - 1) \times 100\%\)

本例:\((e^{0.06}-1) \times 100\% = 6.18\%\),与近似值 6.0% 差别不大。 系数较大(如 \(\hat{\beta}_1 > 0.2\))时,精确公式更准确。

还原预测值:反对数变换

重要

注意: log-level 模型预测的是 \(\ln(y)\),不是 \(y\) 本身。需要做反变换才能得到原始尺度的预测值。

▶️ 查看代码
# 预测经验 = 10 年时的工资
new_data    <- tibble(经验年数 = 10)
pred_log    <- predict(model_log.level, newdata = new_data)
pred_salary <- exp(pred_log)   # 反对数变换

cat("ln(工资) 的预测值:", round(pred_log, 3), "\n")
ln(工资) 的预测值: 8.08 
▶️ 查看代码
cat("工资的预测值(元/月):", round(pred_salary, 0), "\n")
工资的预测值(元/月): 3236 

Part 4:\(x\)\(y\) 同时取对数(log-log 模型)

弹性系数:\(x\) 变化 1%,\(y\) 变化几个百分点?

问题背景:价格与需求量

经济学核心概念: 价格弹性——价格上涨 1%,需求量下降几个百分点?log-log 模型的斜率直接就是弹性系数。

建立 log-log 模型

▶️ 查看代码
set.seed(99)
n <- 80
price_data <- data.frame(价格 = runif(n, 5, 100)) |>
  mutate(需求量 = exp(8 - 1.3 * log(价格) + rnorm(n, sd = 0.2)))

# log-log 模型:x 和 y 同时取对数
model_loglog <- lm(log(需求量) ~ log(价格), data = price_data)
summary(model_loglog)

Call:
lm(formula = log(需求量) ~ log(价格), data = price_data)

Residuals:
   Min     1Q Median     3Q    Max 
-0.564 -0.121  0.012  0.114  0.438 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   7.9100     0.1114    71.0   <2e-16 ***
log(价格)    -1.2857     0.0289   -44.5   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.188 on 78 degrees of freedom
Multiple R-squared:  0.962, Adjusted R-squared:  0.962 
F-statistic: 1.98e+03 on 1 and 78 DF,  p-value: <2e-16

解读 log-log 系数:弹性

回归方程为:

\[\ln(\widehat{\text{需求量}}) = \hat{\beta}_0 - 1.30 \times \ln(\text{价格})\]

如何解读斜率 \(\hat{\beta}_1 = -1.30\)

\[\hat{\beta}_1 = \frac{\Delta\ln y}{\Delta\ln x} \approx \frac{\% \Delta y}{\% \Delta x} = \text{弹性系数}\]

提示

log-log 系数的解读口诀(最简洁):

\(x\) 每增加 1%\(y\) 变化 \(\hat{\beta}_1\%\)

具体说: 价格每上涨 1%,需求量预期下降 1.30%

\(|\hat{\beta}_1| > 1\) → 富有弹性(需求对价格敏感);\(|\hat{\beta}_1| < 1\) → 缺乏弹性。

三种对数模型对比总结

Part 5:分类自变量——两类

用 0/1 虚拟变量表示类别

问题:如何把「类别」放进回归?

线性回归要求自变量是数值型。 但很多重要变量是类别型的:

  • 性别(男 / 女)、是否促销(是 / 否)、是否接受培训(是 / 否)

解决方案:虚拟变量(Dummy Variable)

对于有 2 个类别 的变量,创建 1 个虚拟变量:

\[D = \begin{cases} 1 & \text{类别 A(处理组)} \\ 0 & \text{类别 B(参照组,reference group)} \end{cases}\]

重要

参照组(Reference Group): 虚拟变量系数衡量「与参照组相比的差异」。选哪个类别作参照组不影响预测值和 \(R^2\),但影响系数的数值和解读方向。通常选「基准」或「对照」类别。

案例:促销活动对销量的影响

▶️ 查看代码
set.seed(5)
n <- 100
promo_data <- data.frame(
  广告费 = runif(n, 10, 80),
  促销   = sample(c("无促销", "有促销"), n, replace = TRUE)
) |>
  mutate(
    促销虚拟 = if_else(促销 == "有促销", 1, 0),
    销量     = 5 + 1.2 * 广告费 + 15 * 促销虚拟 + rnorm(n, sd = 6)
  )

# 直接传入字符型变量,R 会自动创建虚拟变量
# "无促销" 按字母顺序排在"有促销"之前,自动成为参照组
model_promo <- lm(销量 ~ 广告费 + 促销, data = promo_data)
summary(model_promo)

Call:
lm(formula = 销量 ~ 广告费 + 促销, data = promo_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-15.183  -3.859   0.073   4.707  14.968 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   5.7422     1.6166    3.55  0.00059 ***
广告费        1.1966     0.0299   39.96  < 2e-16 ***
促销有促销   13.8947     1.2726   10.92  < 2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 6.32 on 97 degrees of freedom
Multiple R-squared:  0.947, Adjusted R-squared:  0.946 
F-statistic:  864 on 2 and 97 DF,  p-value: <2e-16

解读虚拟变量系数

根据输出,回归方程为:

\[\widehat{\text{销量}} = \hat{\beta}_0 + 1.21 \times \text{广告费} + 14.9 \times D_{\text{有促销}}\]

\(\hat{\beta}_{\text{有促销}} = 14.9\) 的含义:

在广告费相同的情况下,有促销活动的月份比无促销月份销量平均高 14.9 万件\(p < 0.001\),极其显著)。

这是促销对销量的净效应——已控制广告费的影响。

注记

两条平行线的直觉: 虚拟变量模型假设两组斜率相同,只有截距不同。橙色线(有促销)整体比蓝色线(无促销)高约 15 个单位——这就是虚拟变量系数的几何意义。

R 如何自动处理因子变量?

▶️ 查看代码
# R 自动选择按字母顺序排列的第一个类别作参照组
# "无促销" < "有促销"(字母顺序),所以"无促销"是参照组

# 查看 R 实际使用的设计矩阵(虚拟变量)
model.matrix(销量 ~ 促销, data = promo_data) |> head(6)
  (Intercept) 促销有促销
1           1          1
2           1          1
3           1          1
4           1          0
5           1          1
6           1          0
▶️ 查看代码
# 显式指定参照组:推荐养成用 factor() + levels 的习惯
promo_data <- promo_data |>
  mutate(促销 = factor(促销, levels = c("无促销", "有促销")))

# 验证:结果与上面完全一致
lm(销量 ~ 广告费 + 促销, data = promo_data) |> coef()
(Intercept)      广告费  促销有促销 
       5.74        1.20       13.89 

提示

实用建议: 养成显式用 factor(levels = ...) 指定顺序的习惯,尤其是类别名称不按预期顺序排列时(如「高/中/低」会被自动排成「低/高/中」)。

Part 6:分类自变量——三类及以上

参照组与多个虚拟变量

规则:\(k\) 个类别,用 \(k-1\) 个虚拟变量

重要

为什么是 \(k-1\) 个,而不是 \(k\) 个?

若创建 \(k\) 个虚拟变量,它们之和恒等于 1,与截距项完全共线(完全多重共线性),OLS 无解。必须去掉一个类别作参照组,被「藏进截距」。

例子:营销渠道(3 个类别)

渠道 \(D_{\text{社交媒体}}\) \(D_{\text{搜索引擎}}\) 预测值
线下门店(参照组) 0 0 \(\hat{\beta}_0\)
社交媒体 1 0 \(\hat{\beta}_0 + \hat{\beta}_1\)
搜索引擎 0 1 \(\hat{\beta}_0 + \hat{\beta}_2\)
  • \(\hat{\beta}_0\):线下门店的基准(均值)
  • \(\hat{\beta}_1\):社交媒体相比线下门店的差异
  • \(\hat{\beta}_2\):搜索引擎相比线下门店的差异

案例一:气缸数对油耗的影响

mtcars 数据: 气缸数(cyl)有 4 缸、6 缸、8 缸三种。气缸数对油耗的净影响有多大?

▶️ 查看代码
# cyl 是数值型,必须先转为因子
mtcars_cyl <- mtcars |>
  mutate(cyl_f = factor(cyl, levels = c(4, 6, 8),
                        labels = c("4缸", "6缸", "8缸")))

# 4缸作参照组(levels 的第一个元素自动成为参照组)
model_cyl <- lm(mpg ~ cyl_f, data = mtcars_cyl)
summary(model_cyl)

Call:
lm(formula = mpg ~ cyl_f, data = mtcars_cyl)

Residuals:
   Min     1Q Median     3Q    Max 
-5.264 -1.836  0.029  1.389  7.236 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   26.664      0.972   27.44  < 2e-16 ***
cyl_f6缸      -6.921      1.558   -4.44  0.00012 ***
cyl_f8缸     -11.564      1.299   -8.90  8.6e-10 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 3.22 on 29 degrees of freedom
Multiple R-squared:  0.732, Adjusted R-squared:  0.714 
F-statistic: 39.7 on 2 and 29 DF,  p-value: 4.98e-09

解读三类虚拟变量系数

根据输出:

\[\widehat{\text{mpg}} = 26.66 - 6.92 \times D_{\text{6缸}} - 11.56 \times D_{\text{8缸}}\]

系数 数值 含义
截距 \(= 26.66\) 4 缸车的平均油耗(英里/加仑)
\(\hat{\beta}_{\text{6缸}} = -6.92\) \(p < 0.001\) 6 缸车比 4 缸平均低 6.92 英里/加仑
\(\hat{\beta}_{\text{8缸}} = -11.56\) \(p < 0.001\) 8 缸车比 4 缸平均低 11.56 英里/加仑

案例二:加入连续型控制变量

更完整的分析: 控制车重后,气缸数的净效应有多大?

▶️ 查看代码
# 同时包含因子变量(气缸数)和连续变量(车重)
model_cyl_wt <- lm(mpg ~ cyl_f + wt, data = mtcars_cyl)
summary(model_cyl_wt)

Call:
lm(formula = mpg ~ cyl_f + wt, data = mtcars_cyl)

Residuals:
   Min     1Q Median     3Q    Max 
-4.589 -1.236 -0.516  1.384  5.792 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   33.991      1.888   18.01  < 2e-16 ***
cyl_f6缸      -4.256      1.386   -3.07  0.00472 ** 
cyl_f8缸      -6.071      1.652   -3.67  0.00100 ***
wt            -3.206      0.754   -4.25  0.00021 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 2.56 on 28 degrees of freedom
Multiple R-squared:  0.837, Adjusted R-squared:  0.82 
F-statistic: 48.1 on 3 and 28 DF,  p-value: 3.59e-11

提示

对比两个模型:

  • model_cyl:气缸数对油耗的「总效应」(未控制车重)
  • model_cyl_wt:控制车重后,气缸数对油耗的「净效应」

观察气缸数系数的变化幅度,可判断车重是否是气缸数与油耗关系中的混淆变量——这正是第 11 讲学到的偏回归系数逻辑。

案例三:钻石切工等级(五类)对价格的影响

▶️ 查看代码
# 切工(cut)有 5 个等级,以"Fair"(最低)为参照组
# 同时控制克拉数(取对数)
diamonds_m <- diamonds |>
  mutate(cut = factor(cut, levels = c("Fair", "Good",
                                      "Very Good", "Premium", "Ideal")))

model_cut <- lm(log(price) ~ cut + log(carat), data = diamonds_m)
summary(model_cut)

Call:
lm(formula = log(price) ~ cut + log(carat), data = diamonds_m)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.5225 -0.1648 -0.0059  0.1609  1.3811 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  8.39201    0.00174 4835.55  < 2e-16 ***
cut.L        0.22433    0.00440   50.97  < 2e-16 ***
cut.Q       -0.06643    0.00389  -17.05  < 2e-16 ***
cut.C        0.05289    0.00340   15.55  < 2e-16 ***
cut^4        0.01863    0.00273    6.81  9.6e-12 ***
log(carat)   1.69577    0.00191  887.68  < 2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.254 on 53934 degrees of freedom
Multiple R-squared:  0.937, Adjusted R-squared:  0.937 
F-statistic: 1.61e+05 on 5 and 53934 DF,  p-value: <2e-16

可视化五类虚拟变量系数

注记

有趣的发现: 控制克拉数后,Ideal(最高切工)相比 Fair 的价格溢价约为 12%。但 PremiumVery Good 之间差异很小——消费者愿意为「顶级切工」额外支付的溢价,远小于为「克拉数」支付的溢价。

Part 7:你必须掌握什么?

学习路线图

必须掌握(核心概念)

重要

以下内容是本课程的基础,期末考试必考,实际工作必用:

  1. 识别何时需要对数变换:散点图弯曲 → 考虑取对数;变量严重右偏 → 考虑取对数

  2. 三种对数模型的系数解读(用一句话表达):

    • level-log:\(x\) 增加 1%,\(y\) 增加 \(\hat{\beta}_1 / 100\)单位
    • log-level:\(x\) 增加 1 单位,\(y\) 增加约 \(\hat{\beta}_1 \times 100\%\);预测时记得 exp() 还原
    • log-log:\(x\) 增加 1%,\(y\) 增加 \(\hat{\beta}_1\%\)(弹性,最简洁)
  3. 虚拟变量的含义:系数 = 该类别相对参照组的均值差(已控制其他变量)

  4. \(k\) 类别用 \(k-1\) 个虚拟变量:去掉一个作参照组;多一个会导致完全共线性,OLS 无法估计

  5. R 操作lm(log(y) ~ log(x))factor(x, levels = ...) 指定参照组;relevel() 修改参照组

理解即可

注记

以下内容理解含义即可,不需要记公式、不需要手算:

  • 对数的近似关系\(\Delta\ln(x) \approx \Delta x / x\),这是「\(x\) 增加 1% 等价于 \(\ln(x)\) 增加 0.01」的数学来源

  • log-level 反变换的精确公式\(\%\Delta y = (e^{\hat{\beta}_1} - 1) \times 100\%\);系数较小时用 \(\hat{\beta}_1 \times 100\%\) 近似即可

  • 虚拟变量回归与单因素 ANOVA 的等价性:纯虚拟变量回归(无其他控制变量)在数学上等价于单因素 ANOVA,\(F\) 统计量相同

  • 交互项:虚拟变量与连续变量相乘(lm(y ~ x * D)),允许两组有不同的斜率——这是下讲内容

常见错误清单

警告

以下是初学者最容易犯的错误,请对照检查:

错误 正确理解
把 level-log 系数解读为「\(x\) 增加 1,\(y\) 增加 \(\hat{\beta}_1\) log-level 的自变量是 \(\ln(x)\)\(x\) 增加 1% 对应 \(\ln(x)\) 增加 \(\approx 0.01\)
忘记对 log-level 预测值做反变换 预测 \(\ln(y)\) 后必须用 exp() 还原,才能得到 \(y\) 的预测值
将有序类别(如 1/2/3 代表低/中/高)直接当数值型使用 数值编码暗含「间距相等」假设,应先用 factor() 转换再建模
创建了 \(k\) 个虚拟变量(含参照组)导致模型报错 只能创建 \(k-1\) 个;R 自动处理,手动创建时记得去掉一列
认为参照组的选择影响模型拟合效果 参照组只影响系数的解读方式,不影响 \(R^2\)、AIC 和任何预测值

知识结构回顾

图 1: 第12讲工作流:对数变换 + 分类变量

本讲小结

  • 对数变换:解决 \(y\)\(x\) 非线性关系的利器;变换后模型仍然是「对系数的线性模型」;只需在 lm() 里用 log() 包裹变量

  • level-loglm(y ~ log(x))\(x\) 增加 1%,\(y\) 增加 \(\hat{\beta}_1/100\) 个单位;适用于收益递减场景

  • log-levellm(log(y) ~ x)\(x\) 增加 1 单位,\(y\) 增加约 \(\hat{\beta}_1 \times 100\%\);预测后用 exp() 还原

  • log-loglm(log(y) ~ log(x))\(\hat{\beta}_1\) 直接是弹性系数;\(x\) 增加 1%,\(y\) 增加 \(\hat{\beta}_1\%\)

  • 两类虚拟变量:1 个虚拟变量,系数 = 两组均值差(控制其他变量后);R 对字符型/因子型自动处理

  • 三类及以上\(k\) 个类别用 \(k-1\) 个虚拟变量,参照组藏进截距;factor(levels = ...) 显式指定参照组

课后练习

基础练习(必做)

  1. 使用 diamonds 数据集,分别建立三个模型预测 price:线性模型(price ~ carat)、level-log 模型(price ~ log(carat))、log-level 模型(log(price) ~ carat、log-log 模型(log(price) ~ log(carat))。用 Adjusted \(R^2\) 和 AIC 比较,判断哪个最优,并用一句话解读最优模型的 carat 系数

  2. 使用 mtcars 数据集,将变速箱类型 am(0 = 自动挡,1 = 手动挡)作为虚拟变量,建立 mpg ~ wt + factor(am) 的回归模型。解释 am 系数的含义,判断手动挡是否显著影响油耗(在控制车重的前提下)

  3. mtcars 中气缸数 cyl 为分类变量,分别以 4 缸8 缸作参照组建立两个纯虚拟变量模型。验证:两个模型的 \(R^2\)、AIC 和拟合值(fitted())完全相同,但系数数值和解读不同

进阶挑战(选做)

  1. 使用 gapminder 包中的 gapminder 数据集(install.packages("gapminder")),建立 log-log 模型:log(lifeExp) ~ log(gdpPercap) + continent。解释 log(gdpPercap) 的弹性系数,以及各洲虚拟变量系数的含义;思考:为什么要同时加入 continent

  2. 综合挑战:在练习 1 的 diamonds 最优模型基础上,加入切工等级 cutfactor(),以 "Fair" 为参照组)。对比加入 cut 前后 Adjusted \(R^2\) 和系数的变化;画出系数图(参考本讲切工案例),解释各等级切工的价格溢价。

下讲预告

第13讲:逻辑回归

  • 当因变量是分类变量

提示

今天的虚拟变量模型探讨的是自变量为分类变量的情形;而下一讲的逻辑回归则将处理因变量为分类变量的情况。这种转换赋予了模型极大的灵活性,是解决现实中‘判断决策’与‘概率预测’问题的核心工具。

谢谢!

第12讲:对数回归与分类自变量


「所有模型都是错的,但有些是有用的。」

—— 乔治·博克斯(George Box)