散点 + 线性回归与 95% 置信带
GAL-0006
用散点展示两个连续变量的关系,叠加最小二乘回归直线及其 95% 置信带,直观呈现趋势和拟合的不确定性。
图与代码

code/R/main.R
suppressPackageStartupMessages(library(ggplot2))
d <- read.csv("data/mtcars.csv", encoding = "UTF-8")
p <- ggplot(d, aes(x = wt, y = mpg)) +
geom_smooth(method = "lm", formula = y ~ x, level = 0.95, n = 80,
colour = "#FC8D62", fill = "#FC8D62", alpha = 0.25, linewidth = 0.9) +
geom_point(size = 2, shape = 21, fill = "#66C2A5", colour = "grey20", stroke = 0.3) +
labs(x = "Weight (1000 lbs)", y = "Fuel economy (miles per gallon)") +
theme_classic(base_size = 12)
ggsave("outputs/figure_r.png", p, width = 6, height = 4.5, dpi = 300, bg = "white")
code/py/main.py
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import scienceplots # noqa: F401
import statsmodels.api as sm
plt.style.use(["science", "no-latex"])
plt.rcParams.update({"font.family": "sans-serif", "font.size": 11}) # 与 R 版(theme_classic 无衬线)统一
d = pd.read_csv("data/mtcars.csv")
fit = sm.OLS(d["mpg"], sm.add_constant(d["wt"])).fit()
# 与 R 版一致:在 wt 范围内取 80 个点,画拟合线与均值的 95% 置信带
grid = np.linspace(d["wt"].min(), d["wt"].max(), 80)
pred = fit.get_prediction(sm.add_constant(grid)).summary_frame(alpha=0.05)
fig, ax = plt.subplots(figsize=(6, 4.5))
ax.fill_between(grid, pred["mean_ci_lower"], pred["mean_ci_upper"], color="#FC8D62", alpha=0.25, linewidth=0)
ax.plot(grid, pred["mean"], color="#FC8D62", lw=1.8)
ax.scatter(d["wt"], d["mpg"], s=28, facecolor="#66C2A5", edgecolor="#333333", linewidth=0.5, zorder=3)
ax.set_xlabel("Weight (1000 lbs)")
ax.set_ylabel("Fuel economy (miles per gallon)")
fig.savefig("outputs/figure_py.png", dpi=300, facecolor="white")什么时候用
- 探索两个连续变量之间的大致线性关系
- 展示回归直线并同时表达平均趋势估计的不确定性
- 样本量不大时,把原始数据点与拟合结果放在一起
常见误用
- 阴影带是平均趋势(条件均值)的 95% 置信带,不是单个观测的预测区间;个体观测的预测区间要宽得多
- 置信带在 x 的均值附近最窄、两端变宽;超出观测范围的外推不可靠,图中拟合线只画到数据范围
- 回归关系不等于因果;本例的相关可能受未纳入变量(如发动机排量、气缸数)影响
- 图中直线以线性关系为前提,应结合残差检查线性、方差齐性等假设是否合理
数据与下载
数据:R 内置数据集 mtcars(datasets 包)(R 内置数据集(随 R 分发,GPL-2 | GPL-3))。32 款汽车的油耗(mpg,英里/加仑)与车重(wt,千磅)。本例拟合 mpg ~ wt 的普通最小二乘线性回归。
下载包 sha256:f65e794367267e03e770991d38fd0b0dc5b316825f2843978398f24c605a2c58