本章學習目標
上一章我們處理一個樣本與一個基準值的比較。臨床與公衛研究更常見的問題是兩組比較:新治療與標準治療哪個好?介入前後是否改善?兩種照護模式的再住院率是否不同?這些都屬於兩樣本推論 (two-sample inference)。
讀完本章後,你應該能夠:
- 區分獨立樣本 (independent samples) 與配對樣本 (paired samples)。
- 執行兩獨立樣本 t 檢定 (two-sample t-test) 與 Welch t 檢定 (Welch’s t-test)。
- 執行配對 t 檢定 (paired t-test)。
- 比較兩個母群體比例 (two population proportions)。
- 建立平均差 (mean difference)、比例差 (risk difference) 與相對風險 (relative risk) 的估計與信賴區間。
- 從效果大小、信賴區間與臨床意義一起解讀兩組比較。
兩組比較先問:獨立還是配對?
兩組資料最重要的第一個問題不是「要按哪個軟體按鈕」,而是資料結構。若兩組來自不同個體,例如標準照護組與介入照護組各自收案不同病人,這通常是獨立樣本。若兩個測量值來自同一個人,例如治療前與治療後血壓,這是配對樣本。
獨立樣本與配對樣本的分析方法不同。配對資料的核心是每個人的前後差異,而不是把治療前與治療後當成兩群陌生人。若忽略配對,會浪費資訊,甚至得到錯誤結論。統計方法很重視資料關係;資料之間若本來有牽手,請不要硬把它們拆散。
兩獨立樣本平均值比較
兩獨立樣本平均值比較常用於比較兩組病人的連續結果,例如收縮壓、LDL-C、住院天數或疼痛分數。令 \(\mu_1\) 與 \(\mu_2\) 為兩組母群體平均值,常見雙尾假設為:
\[
H_0: \mu_1 - \mu_2 = 0
\]
\[
H_1: \mu_1 - \mu_2 \ne 0
\]
若兩組變異數可視為相等,可使用 pooled two-sample t-test。但醫療資料中兩組變異數常不同,Welch t 檢定較穩健,通常是很好的預設選擇。
範例 1:兩組照護模式的收縮壓
假設某研究比較標準照護與介入照護在 12 週後的收縮壓。兩組病人互相獨立。
standard <- c(148, 142, 151, 139, 145, 150, 136, 144, 147, 153, 141, 149, 146, 138, 152, 143)
intervention <- c(136, 132, 141, 129, 135, 138, 131, 134, 137, 140, 133, 139, 130, 128, 142, 136)
bp_groups <- data.frame(
sbp = c(standard, intervention),
group = c(rep("標準照護", length(standard)), rep("介入照護", length(intervention))),
stringsAsFactors = FALSE
)
# 確保組別排序符合描述
bp_groups$group <- factor(bp_groups$group, levels = c("標準照護", "介入照護"))
bp_groups %>%
group_by(group) %>%
summarise(
count = n(),
mean = mean(sbp),
std = sd(sbp),
.groups = "drop"
) %>%
mutate(across(c(mean, std), ~ round(., 2)))
# A tibble: 2 × 4
group count mean std
<fct> <int> <dbl> <dbl>
1 標準照護 16 145. 5.16
2 介入照護 16 135. 4.33
p1 <- ggplot(bp_groups, aes(x = group, y = sbp, fill = group)) +
geom_boxplot(alpha = 0.7, show.legend = FALSE) +
geom_jitter(color = "#333333", alpha = 0.7, width = 0.12, height = 0) +
scale_fill_brewer(palette = "Set2") +
labs(
title = "兩獨立樣本:12 週後收縮壓",
x = "照護組別",
y = "12 週後收縮壓 (mmHg)"
)
p1
welch_result <- t.test(intervention, standard, var.equal = FALSE)
mean_diff <- mean(intervention) - mean(standard)
se_welch <- sqrt(var(intervention) / length(intervention) + var(standard) / length(standard))
df_welch <- (var(intervention) / length(intervention) + var(standard) / length(standard))^2 / (
(var(intervention) / length(intervention))^2 / (length(intervention) - 1) +
(var(standard) / length(standard))^2 / (length(standard) - 1)
)
welch_test_df <- data.frame(
quantity = c("平均差:介入-標準", "Welch t 統計量", "自由度", "p 值", "95% CI 下限", "95% CI 上限"),
value = c(mean_diff, as.numeric(welch_result$statistic), df_welch, welch_result$p.value, welch_result$conf.int[1], welch_result$conf.int[2]),
stringsAsFactors = FALSE
)
welch_test_df$value <- round(welch_test_df$value, 4)
welch_test_df
quantity value
1 平均差:介入-標準 -10.1875
2 Welch t 統計量 -6.0526
3 自由度 29.1220
4 p 值 0.0000
5 95% CI 下限 -13.6294
6 95% CI 上限 -6.7456
平均差為負值,代表介入組平均收縮壓較低。p 值與信賴區間都提供證據支持兩組平均值不同。不過,接著仍要問:下降幅度是否達到臨床上重要?是否有副作用、成本或可行性問題?統計顯著是門票,不是整場演出。
Pooled t 檢定與 Welch t 檢定
Pooled t 檢定假設兩組母群體變異數相同,會把兩組變異合併估計共同變異。Welch t 檢定不要求兩組變異數相等,並使用調整後自由度。實務上,若不確定變異數是否相等,Welch t 檢定通常較安全。
假設變異數相等與否不應只靠「看起來差不多」。更重要的是研究設計與資料來源是否支持這個假設。醫療資料裡,不同病情嚴重度、不同治療路徑常讓變異不一樣。
pooled_result <- t.test(intervention, standard, var.equal = TRUE)
pooled_vs_welch <- data.frame(
method = c("Pooled t-test", "Welch t-test"),
t_statistic = c(as.numeric(pooled_result$statistic), as.numeric(welch_result$statistic)),
p_value = c(pooled_result$p.value, welch_result$p.value),
stringsAsFactors = FALSE
)
pooled_vs_welch$t_statistic <- round(pooled_vs_welch$t_statistic, 4)
pooled_vs_welch$p_value <- round(pooled_vs_welch$p_value, 4)
pooled_vs_welch
method t_statistic p_value
1 Pooled t-test -6.0526 0
2 Welch t-test -6.0526 0
配對樣本平均值比較
配對 t 檢定適用於同一個體的前後測量,或自然配對的資料,例如左右眼、同一病人兩種檢驗方法、同一社區介入前後。配對 t 檢定的關鍵不是比較兩組原始平均值,而是比較「差值」的平均是否為 0。
令 \(D_i = X_{after,i} - X_{before,i}\),假設為:
\[
H_0: \mu_D = 0
\]
\[
H_1: \mu_D \ne 0
\]
若差值平均顯著小於 0,代表治療後數值下降。
範例 2:同一批病人治療前後收縮壓
before <- c(152, 148, 155, 146, 150, 158, 149, 153, 147, 156, 151, 154)
after <- c(140, 138, 144, 139, 141, 146, 137, 142, 136, 145, 139, 143)
paired_df <- data.frame(id = 1:length(before), before = before, after = after)
paired_df$difference <- paired_df$after - paired_df$before
paired_df %>%
select(before, after, difference) %>%
summarise(across(everything(), list(mean = mean, std = sd))) %>%
pivot_longer(everything(), names_to = c("variable", ".value"), names_pattern = "(.*)_(.*)") %>%
mutate(across(c(mean, std), ~ round(., 2)))
# A tibble: 3 × 3
variable mean std
<chr> <dbl> <dbl>
1 before 152. 3.75
2 after 141. 3.21
3 difference -10.8 1.48
paired_long <- paired_df %>%
pivot_longer(cols = c(before, after), names_to = "time", values_to = "sbp") %>%
mutate(time = factor(time, levels = c("before", "after"), labels = c("治療前", "治療後")))
paired_summary <- paired_long %>%
group_by(time) %>%
summarise(
mean_sbp = mean(sbp),
se_sbp = sd(sbp) / sqrt(n()),
lower = mean_sbp - qt(0.975, df = n() - 1) * se_sbp,
upper = mean_sbp + qt(0.975, df = n() - 1) * se_sbp,
.groups = "drop"
)
p2 <- ggplot(paired_long, aes(x = time, y = sbp)) +
geom_line(aes(group = id), color = "#999999", alpha = 0.65) +
geom_line(data = paired_summary, aes(x = time, y = mean_sbp, group = 1), color = "#d62828", linewidth = 1.2) +
geom_errorbar(data = paired_summary, aes(x = time, y = mean_sbp, ymin = lower, ymax = upper), width = 0.1, color = "#d62828", linewidth = 1) +
geom_point(data = paired_summary, aes(x = time, y = mean_sbp), color = "#d62828", size = 3) +
labs(
title = "配對樣本:同一批病人治療前後收縮壓",
x = "時間",
y = "收縮壓 (mmHg)"
)
p2
paired_result <- t.test(after, before, paired = TRUE)
diff_mean <- mean(paired_df$difference)
diff_se <- sd(paired_df$difference) / sqrt(length(paired_df$difference))
paired_test_df <- data.frame(
quantity = c("平均差:後-前", "配對 t 統計量", "p 值", "95% CI 下限", "95% CI 上限"),
value = c(diff_mean, as.numeric(paired_result$statistic), paired_result$p.value, paired_result$conf.int[1], paired_result$conf.int[2]),
stringsAsFactors = FALSE
)
paired_test_df$value <- round(paired_test_df$value, 4)
paired_test_df
quantity value
1 平均差:後-前 -10.7500
2 配對 t 統計量 -25.0807
3 p 值 0.0000
4 95% CI 下限 -11.6934
5 95% CI 上限 -9.8066
配對分析通常比把前後資料當獨立樣本更有效率,因為每位病人都作為自己的對照。個體間差異被抵消後,治療前後差異更容易被看見。
兩比例比較
若結果是二元事件,例如再住院、有無感染、是否達標,常比較兩組比例。常見效果量包括比例差、相對風險與勝算比。本章先聚焦比例差與相對風險。
比例差又稱風險差 (risk difference):
\[
\hat{p}_2 - \hat{p}_1
\]
相對風險 (relative risk, RR) 為:
\[
RR = \frac{\hat{p}_2}{\hat{p}_1}
\]
比例差回答「絕對差多少」,相對風險回答「相對於原本是多少倍」。臨床與公衛決策常需要兩者一起看。
範例 3:兩組 30 天再住院率
prop_df <- data.frame(
group = c("標準照護", "介入照護"),
n = c(180, 175),
readmit = c(42, 26),
stringsAsFactors = FALSE
)
prop_df$rate <- prop_df$readmit / prop_df$n
# 鎖定組別排序
prop_df$group <- factor(prop_df$group, levels = c("標準照護", "介入照護"))
prop_df
group n readmit rate
1 標準照護 180 42 0.2333333
2 介入照護 175 26 0.1485714
p3 <- ggplot(prop_df, aes(x = group, y = rate)) +
geom_col(fill = "#8ab17d", width = 0.6) +
geom_text(aes(label = sprintf("%.1f%%", rate * 100)), vjust = -0.5, size = 4) +
scale_y_continuous(limits = c(0, 0.32)) +
labs(
title = "兩組 30 天再住院率",
x = "照護組別",
y = "30 天再住院率"
)
p3
x1 <- prop_df$readmit[1]
n1 <- prop_df$n[1]
x2 <- prop_df$readmit[2]
n2 <- prop_df$n[2]
p1 <- x1 / n1
p2 <- x2 / n2
pooled_p <- (x1 + x2) / (n1 + n2)
se_null <- sqrt(pooled_p * (1 - pooled_p) * (1 / n1 + 1 / n2))
z_stat <- (p2 - p1) / se_null
p_value <- 2 * min(pnorm(z_stat), 1 - pnorm(z_stat))
diff_prop <- p2 - p1
se_diff_prop <- sqrt(p1 * (1 - p1) / n1 + p2 * (1 - p2) / n2)
ci_prop <- c(diff_prop - qnorm(0.975) * se_diff_prop, diff_prop + qnorm(0.975) * se_diff_prop)
relative_risk <- p2 / p1
prop_test_df <- data.frame(
quantity = c("比例差:介入-標準", "比例差 CI 下限", "比例差 CI 上限", "z 統計量", "p 值", "相對風險"),
value = c(diff_prop, ci_prop[1], ci_prop[2], z_stat, p_value, relative_risk),
stringsAsFactors = FALSE
)
prop_test_df$value <- round(prop_test_df$value, 4)
prop_test_df
quantity value
1 比例差:介入-標準 -0.0848
2 比例差 CI 下限 -0.1660
3 比例差 CI 上限 -0.0036
4 z 統計量 -2.0290
5 p 值 0.0425
6 相對風險 0.6367
比例差為負值,表示介入照護組再住院率較低。相對風險小於 1,也支持介入組風險較低。實務上,比例差常更直觀,因為它可以轉成每 100 位病人少幾位再住院。
效果量與信賴區間
兩樣本推論的重點不只是 p 值,而是效果大小與不確定性。平均差、比例差、相對風險都可以搭配信賴區間呈現。
effect_df <- data.frame(
outcome = c("收縮壓平均差\n介入-標準", "再住院率差\n介入-標準"),
estimate = c(mean_diff, diff_prop),
lower = c(welch_result$conf.int[1], ci_prop[1]),
upper = c(welch_result$conf.int[2], ci_prop[2]),
stringsAsFactors = FALSE
)
# 鎖定因子排序以利圖形顯示順序
effect_df$outcome <- factor(effect_df$outcome, levels = effect_df$outcome)
p4 <- ggplot(effect_df, aes(y = outcome, x = estimate)) +
geom_errorbar(aes(xmin = lower, xmax = upper), width = 0.1, color = "#264653", linewidth = 1) +
geom_point(color = "#d62828", size = 3) +
geom_vline(xintercept = 0, color = "#666666", linetype = "dashed", linewidth = 1) +
labs(
title = "兩樣本推論的效果量",
x = "效果估計與 95% 信賴區間",
y = ""
)
p4
這張圖的尺度不同,主要用來示範概念:效果量最好搭配信賴區間一起報告。若信賴區間很寬,代表不確定性大;若信賴區間跨過 0,代表資料仍與沒有差異相容。
常見陷阱
- 把配對資料當獨立資料分析:會浪費資訊,甚至錯估標準誤。
- 只報 p 值不報平均差或比例差:讀者不知道差異大小。
- 忽略基準風險:相同相對風險在不同基準風險下,絕對影響不同。
- 未檢查變異數與分布形狀:極端偏態或離群值會影響 t 檢定。
- 把統計顯著當成治療值得採用:仍需考慮副作用、成本、可行性與病人偏好。
本章重點整理
- 兩組比較前先判斷資料是獨立樣本或配對樣本。
- Welch t 檢定適合兩獨立樣本平均值比較,且不要求兩組變異數相等。
- 配對 t 檢定分析的是同一個體的差值。
- 兩比例比較可用比例差、相對風險與 p 值描述。
- 效果大小與信賴區間比單獨 p 值提供更多臨床資訊。
- 統計顯著不等於臨床顯著,兩者應分開討論。
小練習
- 說明獨立樣本與配對樣本的差異,並各舉一個醫學例子。
- 某研究兩組平均 LDL-C 分別為 108 與 121 mg/dL,你會如何定義平均差方向?
- 若兩組再住院率分別為 12% 與 18%,計算比例差與相對風險。
- 說明為何配對 t 檢定通常比未配對分析更有效率。
- 解釋「p 值顯著但比例差只有 1%」在臨床上可能代表什麼。
p_standard <- 0.18
p_intervention <- 0.12
practice_risk_difference <- p_intervention - p_standard
practice_relative_risk <- p_intervention / p_standard
practice_results <- data.frame(
quantity = c("比例差:介入-標準", "相對風險:介入/標準"),
value = c(practice_risk_difference, practice_relative_risk),
stringsAsFactors = FALSE
)
practice_results$value <- round(practice_results$value, 4)
practice_results
quantity value
1 比例差:介入-標準 -0.0600
2 相對風險:介入/標準 0.6667
Glossary
| 兩樣本推論 |
two-sample inference |
比較兩組母群體參數的推論方法。 |
| 獨立樣本 |
independent samples |
兩組觀察值來自不同個體且彼此獨立。 |
| 配對樣本 |
paired samples |
兩個觀察值具有自然配對關係,例如同一人前後測。 |
| 兩獨立樣本 t 檢定 |
two-sample t-test |
比較兩獨立樣本平均值的 t 檢定。 |
| Welch t 檢定 |
Welch's t-test |
不假設兩組變異數相等的兩樣本 t 檢定。 |
| Pooled t 檢定 |
pooled t-test |
假設兩組變異數相等並合併變異估計的 t 檢定。 |
| 配對 t 檢定 |
paired t-test |
比較配對差值平均是否為 0 的 t 檢定。 |
| 平均差 |
mean difference |
兩組平均值之差。 |
| 比例差 |
risk difference |
兩組事件比例之差,也稱風險差。 |
| 相對風險 |
relative risk |
兩組事件比例的比值。 |
| 效果量 |
effect size |
差異或關聯大小的量化指標。 |
| 信賴區間 |
confidence interval |
量化估計不確定性的區間。 |
| 統計顯著性 |
statistical significance |
結果達到預設顯著水準的狀態。 |
| 臨床顯著性 |
clinical significance |
結果是否具有實際臨床重要性。 |