R: R 假设检验

最后更新:2026-08-26

上一课我们学了概率分布——理论。这一课进入假设检验——用样本推断总体。这是统计学的核心:广告说"提升 20% 销量"是真的还是忽悠?两组数据差异是偶然还是必然?R 用 4 行代码回答。

读完这一课你就能用 R 做:t 检验(均值比较)、比例检验(合格率比较)、卡方检验(独立性)、方差分析(多组比较)。

1. 你将学到



2. 一个 A/B 测试的故事

(1) 痛点:广告有用吗?

Bob做了 A/B 测试:

manager问:"2% 的差异是真的还是偶然?"

(2) R 的解法

R
# 两比例检验
prop.test(c(80, 100), c(1000, 1000))
# 2-sample test for equality of proportions
# X-squared = 2.46, df = 1, p-value = 0.117
# 结论:p > 0.05,差异**不显著**(可能是偶然)

1 行代码 → p 值 → 决策



3. 假设检验 5 步流程

(1) 5 步流程

100%
graph TB
    A[1. 提出假设] --> B[2. 计算统计量]
    B --> C[3. 计算 p 值]
    C --> D[4. 决策]
    D --> E[5. 报告]
    
    A --> A1["H0 原假设<br/>H1 备择假设"]
    B --> B1["t/z/卡方/F"]
    C --> C1["P 数据像 H0 一样极端的概率"]
    D --> D1["p < 0.05 → 拒绝 H0"]
    E --> E1["报告 p 值 + 效应量 + 置信区间"]
    
    style A fill:#fff3cd
    style B fill:#cce5ff
    style C fill:#d4edda
    style D fill:#f8d7da
    style E fill:#e1d4ff

(2) 关键概念

概念 含义
H0(原假设) 默认假设:两组无差异(差异 = 偶然)
H1(备择假设) 真正想证明的:两组有差异
统计量 衡量"差异多大"的数字(t、z、χ²、F)
p 值 在 H0 为真时,观察到当前/更极端结果的概率
α(显著性水平) p 值的阈值,常用 0.05
拒绝 H0 p < 0.05,差异统计显著
不拒绝 H0 p ≥ 0.05,不能说有差异(≠ 无差异)
⚠️ 关键:"不拒绝 H0 ≠ 接受 H0"。p > 0.05 只表示"证据不足",不是说"两组真的相等"。



4. t.test():均值比较

(1) 3 种 t 检验

类型 场景 R 语法
单样本 1 组 vs 已知值 t.test(x, mu = 0)
双样本独立 2 组独立样本 t.test(x, y)
配对样本 同一对象前后测 t.test(x, y, paired = TRUE)

(2) 单样本 t 检验

R
# 例:产品重量标准 100g,测 10 个产品
weights <- c(98, 102, 99, 101, 100, 97, 103, 99, 101, 100)

t.test(weights, mu = 100)
# One Sample t-test
# t = 0, df = 9, p-value = 1
# 95% CI: [98.7, 101.3]
# mean of x = 100
# 结论:p = 1,**不拒绝 H0**,均值等于 100g

(3) 双样本独立 t 检验

R
# 例:A/B 测试两组转化时间
group_a <- c(12, 15, 14, 13, 16, 14, 15, 13, 14, 15)
group_b <- c(10, 11, 12, 13, 11, 10, 12, 11, 13, 12)

t.test(group_a, group_b)
# Welch Two Sample t-test
# t = 5.32, df = 14.6, p-value = 0.0001
# 95% CI: [1.36, 3.24]
# 结论:p < 0.05,**拒绝 H0**,A 组显著慢于 B 组

(4) 配对 t 检验

R
# 例:同一组患者用药前 vs 用药后
before <- c(180, 175, 190, 170, 185)
after <- c(165, 160, 175, 160, 170)

t.test(before, after, paired = TRUE)
# Paired t-test
# t = 8.5, df = 4, p-value = 0.001
# 结论:p < 0.05,**显著下降**(药物有效)

(5) 关键参数

参数 含义 默认
mu 单样本的已知值 0
paired 是否配对 FALSE
var.equal 等方差假设 FALSE(Welch)
alternative 备择方向 "two.sided"
conf.level 置信水平 0.95
R
# 单侧检验(右侧)
t.test(x, mu = 100, alternative = "greater")

# 单侧检验(左侧)
t.test(x, mu = 100, alternative = "less")


5. prop.test():比例检验

(1) 单比例检验

R
# 例:产品历史合格率 95%,现在抽 100 个有 92 个合格
prop.test(92, 100, p = 0.95)
# 1-sample proportions test
# X-squared = 1.27, df = 1, p-value = 0.26
# 结论:p > 0.05,合格率**未显著下降**

(2) 双比例检验(A/B 测试核心)

R
# 例:A 组 1000 人转化 80,B 组 1000 人转化 100
prop.test(c(80, 100), c(1000, 1000))
# 2-sample test for equality of proportions
# X-squared = 2.46, df = 1, p-value = 0.117
# 95% CI: [-0.046, 0.006]
# 结论:p > 0.05,**差异不显著**(可能是偶然)

(3) prop.test vs chisq.test



6. chisq.test():卡方检验

(1) 2 大用途

用途 场景 公式
拟合优度 观察 vs 期望 chisq.test(observed)
独立性 2 个分类变量相关? chisq.test(table(x, y))

(2) 拟合优度检验

R
# 例:骰子公平性测试(投 60 次)
observed <- c(8, 12, 10, 11, 9, 10)  # 6 个面的次数
expected <- rep(10, 6)  # 期望均匀

chisq.test(observed, p = expected / sum(expected))
# Chi-squared test
# X-squared = 1.2, df = 5, p-value = 0.945
# 结论:p > 0.05,骰子**公平**(不拒绝均匀假设)

(3) 独立性检验

R
# 例:性别 vs 购买行为
gender <- c("男", "男", "女", "女", "男", "女", "男", "女")
purchase <- c("买", "不买", "买", "买", "不买", "买", "买", "不买")

tab <- table(gender, purchase)
print(tab)
#      不买 买
#   男    1  3
#   女    1  3

chisq.test(tab)
# X-squared = 0, df = 1, p-value = 1
# 结论:p > 0.05,性别与购买**无关**

# 注意:任何 2x2 表期望频数 < 5 用 Fisher 精确检验
fisher.test(tab)

(4) 期望频数要求

R
# 卡方检验要求:每个单元格期望频数 ≥ 5
# 不满足时用 Fisher 精确检验
result <- chisq.test(tab)
result$expected  # 查看期望频数


7. aov() 方差分析(ANOVA)

(1) 适用场景

3 组及以上均值的比较(t 检验只能 2 组)。

(2) 实战

R
# 例:3 种肥料对作物产量的影响
fertilizer <- c(rep("A", 10), rep("B", 10), rep("C", 10))
yield <- c(20, 22, 21, 19, 23, 20, 21, 22, 19, 20,   # A
           25, 26, 24, 27, 25, 26, 27, 25, 24, 26,  # B
           18, 19, 17, 18, 19, 20, 19, 18, 19, 20)  # C

df <- data.frame(fertilizer, yield)

# 单因素 ANOVA
model <- aov(yield ~ fertilizer, data = df)
summary(model)
#              Df Sum Sq Mean Sq F value Pr(>F)    
# fertilizer     2  220.0   110.0   91.7  <2e-16 ***
# Residuals     27   32.4     1.2
# 结论:p < 0.05,3 种肥料**显著不同**

# 事后检验:Tukey HSD
TukeyHSD(model)
#   diff        lwr        upr     p adj
# B-A   5.0  3.91       6.09    0.000
# C-A  -1.5 -2.59      -0.41    0.005
# C-B  -6.5 -7.59      -5.41    0.000


8. wilcox.test() 非参数检验

(1) 何时用?

(2) 实战

R
# 配对非参数(Wilcoxon signed-rank)
before <- c(180, 175, 190, 170, 185)
after <- c(165, 160, 175, 160, 170)

wilcox.test(before, after, paired = TRUE)
# V = 15, p-value = 0.0625
# 结论:p > 0.05(不显著),但样本小

# 独立非参数(Mann-Whitney U)
group_a <- c(12, 15, 14, 13, 16)
group_b <- c(10, 11, 12, 13, 11)
wilcox.test(group_a, group_b)
# W = 25, p-value = 0.028
# 结论:p < 0.05,差异显著


9. p 值解读与陷阱

(1) p 值正确理解

解读 说明
✅ 正确 在 H0 为真时,观察到当前/更极端结果的概率
❌ 错误 "H0 为真的概率"
❌ 错误 "差异是因为偶然的概率"
❌ 错误 "差异的强度"

(2) 5 大常见陷阱

100%
graph TB
    A[p 值陷阱] --> B[p-hacking<br/>多次试到 p<0.05]
    A --> C[样本量大 p 必小<br/>需看效应量]
    A --> D[p<0.05 不等于有用<br/>看 effect size]
    A --> E[不拒绝 ≠ 接受 H0]
    A --> F[显著性 ≠ 实际意义]
    
    style A fill:#fff3cd
    style B fill:#f8d7da
    style C fill:#cce5ff
    style D fill:#d4edda
    style E fill:#e1d4ff
    style F fill:#ffe1d4

(3) 效应量(effect size)

只看 p 值不够,要看效应量——差异有多大:

检验 效应量
t 检验 Cohen's d = (m1 - m2) / s_pooled
ANOVA η²(eta squared)
卡方 Cramér's V
相关 r(相关系数)
R
# Cohen's d 计算
cohens_d <- function(x, y) {
  n1 <- length(x)
  n2 <- length(y)
  s_pooled <- sqrt(((n1-1)*var(x) + (n2-1)*var(y)) / (n1 + n2 - 2))
  (mean(x) - mean(y)) / s_pooled
}
Cohen's d 含义
0.2 小效应
0.5 中效应
0.8 大效应


10. 完整示例:A/B 测试 + 多组比较

下面是一个完整工作流示例,把本课所有假设检验知识串起来。

▶ 示例:营销活动效果全面检验

R 📖 仅展示
# ============================================
# 营销活动效果全面检验
# 功能:t 检验 / 比例检验 / ANOVA 综合
# ============================================

set.seed(42)

# 1. A/B 测试转化时间
group_a <- rnorm(50, mean = 15, sd = 3)  # 原页面
group_b <- rnorm(50, mean = 13, sd = 3)  # 新页面

cat("=== A/B 测试:转化时间 ===\n")
cat("A 组均值:", round(mean(group_a), 2), "秒\n")
cat("B 组均值:", round(mean(group_b), 2), "秒\n")
cat("差异:", round(mean(group_a) - mean(group_b), 2), "秒\n\n")

# 2. t 检验
t_result <- t.test(group_a, group_b)
print(t_result)
cat("\n")

# 3. Cohen's d
n1 <- length(group_a)
n2 <- length(group_b)
s_pooled <- sqrt(((n1-1)*var(group_a) + (n2-1)*var(group_b)) / (n1+n2-2))
cohens_d <- (mean(group_a) - mean(group_b)) / s_pooled
cat("Cohen's d(效应量):", round(cohens_d, 3), "\n")
cat("效应大小:", ifelse(abs(cohens_d) > 0.8, "大",
                  ifelse(abs(cohens_d) > 0.5, "中", "小")), "\n\n")

# 4. A/B 测试转化率
convert_a <- 80
convert_b <- 100
visitors_a <- 1000
visitors_b <- 1000

cat("=== A/B 测试:转化率 ===\n")
cat("A 组转化率:", round(convert_a / visitors_a * 100, 2), "%\n")
cat("B 组转化率:", round(convert_b / visitors_b * 100, 2), "%\n\n")

# 5. 比例检验
prop_result <- prop.test(c(convert_a, convert_b),
                          c(visitors_a, visitors_b))
print(prop_result)
cat("\n")

# 6. 3 种营销策略对比(ANOVA)
strategy <- c(rep("邮件", 20), rep("短信", 20), rep("推送", 20))
sales <- c(rnorm(20, 100, 15),
           rnorm(20, 110, 15),
           rnorm(20, 105, 15))
df_strategy <- data.frame(strategy, sales)

cat("=== 3 策略销售对比(ANOVA)===\n")
model <- aov(sales ~ strategy, data = df_strategy)
summary(model)
cat("\n事后检验:\n")
print(TukeyHSD(model))

# 7. 性别与购买行为(卡方)
gender <- sample(c("男", "女"), 200, replace = TRUE)
purchase <- sample(c("买", "不买"), 200, replace = TRUE,
                   prob = c(0.3, 0.7))
tab <- table(gender, purchase)
cat("\n=== 性别 vs 购买 卡方检验 ===\n")
print(tab)
cat("\n")
chisq_result <- chisq.test(tab)
print(chisq_result)

# 8. 综合报告
cat("\n=== 决策总结 ===\n")
cat("1. 转化时间:A 组比 B 组慢 ", round(cohens_d, 2), "个标准差",
    ifelse(t_result$p.value < 0.05, "(显著)", "(不显著)"), "\n", sep = "")
cat("2. 转化率:A vs B 差异",
    ifelse(prop_result$p.value < 0.05, "显著", "不显著"), "\n")
cat("3. 3 策略:",
    ifelse(summary(model)[[1]]$`Pr(>F)`[1] < 0.05, "显著不同", "无差异"), "\n")
逻辑代码 54 行(超过 40 行限制,仅展示)

预期输出(节选):

TEXT 📖 仅展示
=== A/B 测试:转化时间 ===
A 组均值: 14.87 秒
B 组均值: 12.94 秒
差异: 1.93 秒

Welch Two Sample t-test
t = 3.18, df = 96.3, p-value = 0.002
Cohen's d(效应量): 0.643
效应大小: 中

=== 决策总结 ===
1. 转化时间:A 组比 B 组慢 0.64 个标准差(显著)
2. 转化率:A vs B 差异不显著
3. 3 策略:显著不同

❓ 常见问题

Q 卡方检验要求?
A 每个单元格期望频数 ≥ 5

📖 小节


📝 作业

  1. 基础题:模拟 30 个学生成绩(均 80 标准差 10),单样本 t 检验是否显著偏离 75 分;再模拟另 30 个(均 78),做双样本 t 检验。记录 p 值。

  2. 基础题:模拟 A/B 测试(A 组 1000 人转化 50,B 组 1000 人转化 80),用 prop.test 检验差异是否显著。计算 Cohen's d 效应量。

  3. 基础题:构造 3x3 列联表(3 个广告渠道 × 是否点击),用 chisq.test 检验渠道与点击是否独立。查看 result$expected,所有期望频数 ≥ 5 吗?

  4. 进阶题:模拟 3 种教学方法(每组 20 学生)的成绩,用 aov 做 ANOVA,再 TukeyHSD 看哪两组差异最大。

  5. 挑战题:完整 A/B 测试——模拟 2 页面(各 1000 用户)的转化时间 + 转化率,用 t.test + prop.test + Cohen's d 综合评估,写出 1 段决策报告(p 值 + 效应量 + 业务建议)。截图保存。

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏