R2 分解与 FWL定理:用韦恩图看懂回归表
2026/6/16 17:31:50 网站建设 项目流程

温馨提示:若页面不能正常显示数学公式和代码,请阅读原文获得更好的阅读体验。

整理人:李增杰 (南开大学)
邮箱:Lazaroo@163.com
Source:Andrew Heiss, 2021,Exploring R² and regression variance with Euler/Venn diagrams. Link

  • 类别:回归分析
  • Title: R2 分解与 FWL定理:用韦恩图看懂回归表
  • Keywords: Frisch–Waugh–Lovell 定理, R平方, R-sqaure, R2分解, 系数含义, 回归系数

1. 基本说明:为什么 R2 容易被误读?

初学计量的人,拿到回归表时,第一眼会瞄向 R2R2:如果 R2=0.02R2=0.02,就觉得模型解释力太弱,结果“不够好”;如果 R2=0.85R2=0.85,会觉得拟合的不错。

这个习惯可以理解,因为 R2R2 比标准误、似然值、AIC、BIC 更容易读懂。它似乎直接回答了一个问题:这个模型到底解释了多少?

但问题在于:越容易读懂的指标,越容易被过度解释。R2R2 的确有用。它告诉我们,在当前样本和当前模型设定下,解释变量合起来解释了 YY 总波动的多少。但它不能直接告诉我们:

  • 某个核心解释变量是否具有因果含义;
  • 控制变量是否放得合理;
  • 哪个解释变量更重要;
  • 回归系数能不能解释为“控制其他变量不变”;
  • IV / 2SLS 中负的 R2R2 是否意味着模型失败。

这些问题都和 R2R2 有关,但又不能只靠 R2R2 回答。

本文用 R 模拟数据和韦恩图来解释 R2R2。在此基础上,我们进一步引入 FWL 定理和 R2 分解。直观地说:

  • R2R2 回答的是:模型整体解释了多少 YY 的波动;
  • FWL 定理回答的是:在控制其他变量以后,某个核心变量的系数来自哪里;
  • R2 分解回答的是:完整模型的解释力如何分摊到不同解释变量上。

这三个问题看似接近,实际上对应回归表中的三个不同层次。

2. 环境搭建

本文主要使用 R 语言完成模拟、回归和绘图。需要安装和加载如下包:

# 安装相关包 install.packages("tidyverse") # 数据整理与绘图 install.packages("broom") # 整理模型输出 install.packages("gapminder") # Gapminder 示例数据 install.packages("faux") # 生成相关模拟数据 install.packages("eulerr") # 绘制欧拉图和韦恩图 install.packages("patchwork") # 拼接图形 install.packages("latex2exp") # 在图形中加入 LaTeX 公式 # 加载相关包 library(tidyverse) library(broom) library(gapminder) library(faux) library(eulerr) library(patchwork) library(grid) library(latex2exp)

这些包的作用并不复杂。tidyverse用于数据整理和基本绘图;broom可以把模型结果整理为数据框;gapminder提供一个直观的现实数据例子;faux用来生成具有指定相关结构的模拟数据;eulerr用来绘制变量之间重叠关系的欧拉图。

3. 一个简单例子:人均 GDP 与预期寿命

回归中的 R2R2 可以理解为:模型解释了被解释变量总波动的多少。

设一元线性回归模型为:

Yi=α+βXi+uiYi​=α+βXi​+ui​

在含截距项的 OLS 回归中,有如下平方和分解:

SST=SSR+SSESST=SSR+SSE

其中:

SST=∑i(Yi−Yˉ)2SST=i∑​(Yi​−Yˉ)2

SSR=∑i(Y^i−Yˉ)2SSR=i∑​(Y^i​−Yˉ)2

SSE=∑i(Yi−Y^i)2SSE=i∑​(Yi​−Y^i​)2

于是:

R2=SSRSST=1−SSESSTR2=SSTSSR​=1−SSTSSE​

这就是 R2R2 最常见的定义。它衡量模型解释掉的 YY 的波动占 YY 总波动的比例。

下面用gapminder数据做一个简单例子。我们只使用 2007 年数据,用各国人均 GDP 解释预期寿命。

# 只保留 2007 年数据 gapminder_2007 <- gapminder %>% filter(year == 2007) # 使用人均 GDP 解释预期寿命 super_naive_model <- lm( lifeExp ~ gdpPercap, data = gapminder_2007 ) # 查看回归系数 tidy(super_naive_model) # 查看 R2 等模型诊断指标 glance(super_naive_model)

示例输出如下:

## # A tibble: 2 × 5 ## term estimate std.error statistic p.value ## <chr> <dbl> <dbl> <dbl> <dbl> ## 1 (Intercept) 59.6 1.01 59.0 9.89e-101 ## 2 gdpPercap 0.000637 0.0000583 10.9 1.69e-20
## # A tibble: 1 × 12 ## r.squared adj.r.squared sigma statistic p.value ## <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 0.461 0.457 8.90 120. 1.69e-20

这里的 R2R2 大约为 0.461。也就是说,在这个简单模型中,人均 GDP 可以解释各国预期寿命差异中约 46.1% 的波动。

这个结果不难理解。富裕国家通常有更好的医疗、营养、公共卫生和教育条件,因此人均 GDP 与预期寿命之间存在较强相关关系。

但我们要小心:R2=0.461R2=0.461 并不等于“人均 GDP 对预期寿命有 46.1% 的因果影响”。它只是说,在当前样本和当前模型下,人均 GDP 与预期寿命之间有较大的共同波动。

因此,R2R2 是拟合优度指标,不是因果识别指标。

4. 重叠圆圈形式的回归

公式可以说明 R2R2 的定义,但不一定帮助我们理解多元回归中的重叠关系。一个更直观的方式,是把变量看成圆圈。

每个圆的面积表示一个变量的波动。两个圆的重叠部分表示两个变量之间的共同波动。对回归而言,YY 和解释变量重叠的那部分,就是模型能够解释的 YY 的波动。

这种图在早期文献中常被称为ballantine图,也可以理解为一种欧拉图或韦恩图。它不能替代严格统计推断,但很适合帮助我们理解 R2R2、控制变量和多重共线性。

4.1 模拟一组三变量数据

为了让图形更清楚,我们先生成一组模拟数据。设有三个变量 YY、X1X1 和 X2X2。三个变量都服从正态分布,并且彼此之间存在一定相关性。

设定如下:

Y: mean=10, sd=2Y: mean=10, sd=2

X1: mean=9, sd=1.7X1: mean=9, sd=1.7

X2: mean=9, sd=1.3X2: mean=9, sd=1.3

相关系数设为:

corr(Y,X1)=0.5corr(Y,X1)=0.5

corr(Y,X2)=0.3corr(Y,X2)=0.3

corr(X1,X2)=0.4corr(X1,X2)=0.4

使用faux包生成数据:

set.seed(1234) df <- rnorm_multi( n = 100, mu = c(10, 9, 9), sd = c(2, 1.7, 1.3), r = c(0.5, 0.3, 0.4), varnames = c("Y", "X1", "X2"), empirical = FALSE ) # 查看前几行数据 head(df) # 查看相关系数 cor(df)

示例输出如下:

## Y X1 X2 ## 1 8.22 6.73 8.38 ## 2 10.17 9.36 10.12 ## 3 12.03 10.32 9.86 ## 4 5.41 5.80 8.38 ## 5 10.10 10.08 10.09 ## 6 11.13 9.11 9.94
## Y X1 X2 ## Y 1.000 0.453 0.373 ## X1 0.453 1.000 0.468 ## X2 0.373 0.468 1.000

后面的图都基于这组三变量数据。

为了用面积表示变量波动,我们写一个函数来计算变量的离均差平方和:

# 计算变量的离均差平方和 ss <- function(x) { sum((x - mean(x))^2) }

这里使用平方和而不是方差,是因为aov()输出中直接包含平方和,后面计算更方便。

温馨提示:若页面不能正常显示数学公式和代码,请阅读原文获得更好的阅读体验。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询