Rによる仮説検定:t.test、prop.test、chisq.testの完全チュートリアル
前回のレッスンでは、確率分布について――その理論――を学びました。今回のレッスンでは、仮説検定――標本を用いて母集団について結論を導き出す方法――について詳しく見ていきます。これが統計学の核心です。「売上が20%増加」と謳う広告は本当なのか、それとも単なる誇大宣伝なのか? 2つのデータセットの差は偶然によるものなのか、それとも必然的なものなのか? Rを使えば、たった4行のコードでこの疑問に答えることができます。
このレッスンを修了すると、R を使用して、t 検定(平均値の比較)、割合の検定(合格率の比較)、カイ二乗検定(独立性の検定)、および分散分析(複数の群の比較)を行うことができるようになります。
1. 学習内容
- 仮説検定の5段階のプロセス(帰無仮説/対立仮説/検定統計量/p値/判定)
- t.test:1標本、2標本、対応のあるt検定
- prop.test 比例性検定
- chisq.test カイ二乗検定(独立性/適合度)
- ANOVA(分散分析)
- 非パラメトリック検定:wilcox.test
- p値の解釈とよくある落とし穴
2. A/Bテストに関する話
(1) 課題:広告は効果があるのか?
ボブはA/Bテストを実施しました:
- グループA(旧広告):1,000人、コンバージョン80件(8%)
- グループB(新規広告):1,000人、コンバージョン100件(10%)
マネージャーは「この2%の差は本当なのか、それとも単なる偶然なのか?」と尋ねた。
(2) Rを用いた解決策
# Two-Proportion Test
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
# Conclusion: p > 0.05, Differences Not significant (It might be a coincidence.)
1行のコード → p値 → 決定。
3. 仮説検定の5段階のプロセス
(1) 5つのステップ
graph TB
A[1. Propose a hypothesis] --> B[2. Calculate the statistic]
B --> C[3. Calculation p-value]
C --> D[4. Decision-making]
D --> E[5. Report]
A --> A1["H0 Null Hypothesis<br/>H1 Alternative Hypothesis"]
B --> B1["t/z/Chi-square/F"]
C --> C1["P Data Visualization H0 An equally extreme probability"]
D --> D1["p < 0.05 → Reject H0"]
E --> E1["Report p-value + Effect size + Confidence Interval"]
style A fill:#fff3cd
style B fill:#cce5ff
style C fill:#d4edda
style D fill:#f8d7da
style E fill:#e1d4ff
(2) 主要な概念
| 概念 | 意味 |
|---|---|
| H0(帰無仮説) | デフォルトの仮定:2つのグループは区別がつかない(差は偶然によるもの) |
| H1(対立仮説) | 私たちが本当に証明したいこと:2つのグループには違いがあるということ |
| 統計量 | 「差がどれほど大きいか」を測る数値(t、z、χ²、F) |
| p値 | H0が真であると仮定した場合に、現在の結果またはそれよりも極端な結果が観測される確率 |
| α(有意水準) | p値の閾値。一般に0.05 |
| H0を棄却 | p < 0.05、差は統計的に有意 |
| H0を棄却しない | p ≥ 0.05;差があるとは結論づけられない(≠ 差がない) |
4. t.test(): 平均値の比較
(1) t検定の3つの種類
| タイプ | シナリオ | R構文 |
|---|---|---|
| 単一サンプル | 1群対既知値 | t.test(x, mu = 0) |
| 2つの独立した標本 | 2つの独立した標本 | t.test(x, y) |
| 対応のある標本 | 同一被験者を対象とした事前・事後テスト | t.test(x, y, paired = TRUE) |
(2) 1標本t検定
# Example: Product Weight Standard 100g, test 10 products
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
# Conclusion: p = 1, Don't reject H0, the mean is equal to 100g
(3) 2標本独立t検定
# Example: A/B Testing the conversion times for two groups
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]
# Conclusion: p < 0.05, Reject H0, Group A was significantly slower than Group B
(4) 対応のあるt検定
# Example: Before medication vs after medication in the same group of patients
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
# Conclusion: p < 0.05, Significant decline (The medication is effective)
(5) 主要なパラメータ
| パラメータ | 意味 | デフォルト |
|---|---|---|
mu |
単一サンプルの既知値 | 0 |
paired |
ペアリングされていますか? | FALSE |
var.equal |
同分散性の仮定 | FALSE (ウェルチ) |
alternative |
別の方向 | 「two.sided」 |
conf.level |
信頼水準 | 0.95 |
# One-sided test (right-tailed)
t.test(x, mu = 100, alternative = "greater")
# One-sided test (left-tailed)
t.test(x, mu = 100, alternative = "less")
5. prop.test(): 比例性の検定
(1) 1つの比率の検定
# Example: Historical Product Pass Rate 95%, now 92 out of 100 are Qualified
prop.test(92, 100, p = 0.95)
# 1-sample proportions test
# X-squared = 1.27, df = 1, p-value = 0.26
# Conclusion: p > 0.05, Pass Rate No significant decrease
(2) 二比例検定(A/Bテストの中核)
# Example: Group A 1000 people, 80 conversions; Group B 1000 people, 100 conversions
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]
# Conclusion: p > 0.05, The difference is not significant (It might be a coincidence.)
(3) prop.test 対 chisq.test
prop.test(c(s1, s2), c(n1, n2))=chisq.test(matrix(c(s1, n1-s1, s2, n2-s2), 2))prop.test連続性の修正を追加(推奨)
6. chisq.test(): カイ二乗検定
(1) 2つの主な用途
| 目的 | シナリオ | 計算式 |
|---|---|---|
| 適合度 | 観測値と予測値の比較 | chisq.test(observed) |
| 独立性 | 2つのカテゴリ変数には相関があるか? | chisq.test(table(x, y)) |
(2) 適合度検定
# Example: Dice Fairness Test (toss 60 times)
observed <- c(8, 12, 10, 11, 9, 10) # Number of times each face appears
expected <- rep(10, 6) # Expect uniformity
chisq.test(observed, p = expected / sum(expected))
# Chi-squared test
# X-squared = 1.2, df = 5, p-value = 0.945
# Conclusion: p > 0.05, Dice is fair (Do not reject the uniformity assumption)
(3) 独立性の検定
# Example: Gender vs Purchasing Behavior
gender <- c("M", "M", "F", "F", "M", "F", "M", "F")
purchase <- c("Buy", "Not buying", "Buy", "Buy", "Not buying", "Buy", "Buy", "Not buying")
tab <- table(gender, purchase)
print(tab)
# Not buying Buy
# M 1 3
# F 1 3
chisq.test(tab)
# X-squared = 0, df = 1, p-value = 1
# Conclusion: p > 0.05, Gender and Purchasing Independent
# Note: Any 2x2 Table with Expected Frequencies < 5, use Fisher's Exact Test
fisher.test(tab)
(4) 期待される頻度に関する要件
# Chi-Square Test Requirements: Expected Frequency for Each Cell >= 5
# Use Fisher's Exact Test when not satisfied
result <- chisq.test(tab)
result$expected # View Expected Frequency
7. aov() 分散分析(ANOVA)
(1) 適用されるシナリオ
3つ以上のグループ間の平均値の比較(t検定は2つのグループに限定されます)。
(2) 実践的な応用
# Example: Effect of 3 Fertilizer Types on Crop Yields
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)
# Single-factor 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
# Conclusion: p < 0.05, 3 Fertilizer Types Significant difference
# Post-hoc comparison: 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) いつ使うべきか?
- データは正規分布ではない(したがって、t検定は使用できない)
- サンプルサイズが小さい(n < 30)
- 極端な外れ値がある
- 順序データ(「優秀/良好/平均/不良」など)
(2) 実践的な応用
# Non-parametric paired test (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
# Conclusion: p > 0.05 (Not significant), however, the sample size is small
# Independent non-parametric (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
# Conclusion: p < 0.05, the difference is significant
9. p値の解釈とよくある落とし穴
(1) p値の正しい理解
| 解釈 | 説明 |
|---|---|
| ✅ 正解 | H0が真である場合に、現在の結果またはそれ以上の極端な結果が観測される確率 |
| ❌ エラー | 「H0が真である確率」 |
| ❌ エラー | 「この差は偶然によるものである」 |
| ❌ エラー | 「差の大きさ」 |
(2) よくある5つの落とし穴
graph TB
A[p Value Trap] --> B[p-hacking<br/>After trying it several times p<0.05]
A --> C[Large sample size p Bi Xiao<br/>Depends on the effect size]
A --> D[p<0.05 Does not mean it is useful<br/>Check effect size]
A --> E[Don't refuse ≠ Accept H0]
A --> F[Significance ≠ Practical Significance]
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) 効果量
p値だけを見るだけでは不十分です。効果量、つまりその差がどれほど大きいかを確認する必要があります:
| 検定 | 効果量 |
|---|---|
| t検定 | コーエンのd = (m1 - m2) / s_pooled |
| ANOVA | η²(エータ二乗) |
| カイ二乗 | クレイマーのV |
| 相関 | r(相関係数) |
# Cohen's d Calculation
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
}
| コーエンのd | 意味 |
|---|---|
| 0.2 | 効果が小さい |
| 0.5 | 中程度の効果 |
| 0.8 | 大きな効果 |
10. 完全な例:A/Bテスト+多群比較
以下は、このレッスンで取り上げた仮説検定の概念をすべて結びつけた完全なワークフローの例です。
▶ サンプル:マーケティングキャンペーンの成果に関する包括的な評価
# ============================================
# Comprehensive Evaluation of Marketing Campaign Performance
# Features: t-test / Proportionality Test / ANOVA combined
# ============================================
set.seed(42)
# 1. A/B Test Conversion Time
group_a <- rnorm(50, mean = 15, sd = 3) # Original Page
group_b <- rnorm(50, mean = 13, sd = 3) # New Page
cat("=== A/B Test: Conversion Time ===\n")
cat("A Group Mean:", round(mean(group_a), 2), "s\n")
cat("B Group Mean:", round(mean(group_b), 2), "s\n")
cat("Differences:", round(mean(group_a) - mean(group_b), 2), "s\n\n")
# 2. t-test
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 (Effect size):", round(cohens_d, 3), "\n")
cat("Effect Size:", ifelse(abs(cohens_d) > 0.8, "L",
ifelse(abs(cohens_d) > 0.5, "Mid", "S")), "\n\n")
# 4. A/B Testing Conversion Rates
convert_a <- 80
convert_b <- 100
visitors_a <- 1000
visitors_b <- 1000
cat("=== A/B Test: Conversion Rate ===\n")
cat("A Group Conversion Rate:", round(convert_a / visitors_a * 100, 2), "%\n")
cat("B Group Conversion Rate:", round(convert_b / visitors_b * 100, 2), "%\n\n")
# 5. Proportionality Test
prop_result <- prop.test(c(convert_a, convert_b),
c(visitors_a, visitors_b))
print(prop_result)
cat("\n")
# 6. Comparison of 3 Marketing Strategies (ANOVA)
strategy <- c(rep("Email", 20), rep("Text Message", 20), rep("Push", 20))
sales <- c(rnorm(20, 100, 15),
rnorm(20, 110, 15),
rnorm(20, 105, 15))
df_strategy <- data.frame(strategy, sales)
cat("=== Comparison of 3 Sales Strategies (ANOVA) ===\n")
model <- aov(sales ~ strategy, data = df_strategy)
summary(model)
cat("\nPost-hoc comparison:\n")
print(TukeyHSD(model))
# 7. Gender and Purchasing Behavior (Chi-square)
gender <- sample(c("M", "F"), 200, replace = TRUE)
purchase <- sample(c("Buy", "Not buying"), 200, replace = TRUE,
prob = c(0.3, 0.7))
tab <- table(gender, purchase)
cat("\n=== Gender vs Purchase Chi-Square Test ===\n")
print(tab)
cat("\n")
chisq_result <- chisq.test(tab)
print(chisq_result)
# 8. Comprehensive Report
cat("\n=== Summary of Decisions ===\n")
cat("1. Conversion Time: Group A is", round(cohens_d, 2), "standard deviations slower than Group B",
ifelse(t_result$p.value < 0.05, " (Significant)", " (Not significant)"), "\n", sep = "")
cat("2. Conversion Rate: A vs B Difference",
ifelse(prop_result$p.value < 0.05, "Significant", "Not significant"), "\n")
cat("3. 3 Strategies:",
ifelse(summary(model)[[1]]$`Pr(>F)`[1] < 0.05, "Significant difference", "No difference"), "\n")
期待される出力(抜粋):
=== A/B Test: Conversion Time ===
A Group Mean: 14.87 s
B Group Mean: 12.94 s
Differences: 1.93 s
Welch Two Sample t-test
t = 3.18, df = 96.3, p-value = 0.002
Cohen's d (Effect size): 0.643
Effect Size: Mid
=== Summary of Decisions ===
1. Conversion Time: Group A is 0.64 standard deviations slower than Group B (Significant)
2. Conversion Rate: A vs B The difference is not significant
3. 3 Strategies: Significant difference
❓ よくある質問
📖 まとめ
- 5つのステップで学ぶ仮説検定:H0/H1 → 検定統計量 → p値 → 判定 → 結果の報告
- t検定:
t.test(x, y)2標本 /paired = TRUE対応のある /mu =1標本 - 比例テスト:
prop.test(c(s1, s2), c(n1, n2))A/Bテストに使用される - カイ二乗検定:
chisq.test(table)独立性 /chisq.test(observed)適合度 - ANOVA:
aov(y ~ group)複数の群間の平均値の比較;続いてTukeyHSD() - p値 ≠ 効果の大きさ—効果量(コーエンのd/η²)と併せて使用する必要がある
- 5つの主な落とし穴:p-ハッキング、標本サイズの大きさがp値の小ささを招くこと、p < 0.05 ≠ 臨床的に有意であること、帰無仮説を棄却できないこと ≠ 帰無仮説の受け入れ、および統計的有意性 ≠ 実用的な有意性
- p < 0.05 が統計的有意性の閾値である。実用的な有意性は、効果の大きさとビジネス上の文脈によって異なる。
📝 練習問題
-
基本問題:30人の学生の得点(平均80、標準偏差10)をシミュレーションし、75点から有意な乖離があるかどうかを判断するために1標本t検定を行う。次に、別の30人の学生の得点(平均78)をシミュレーションし、2標本t検定を行う。p値を記録せよ。
-
基本問題:A/Bテストをシミュレートする(グループA:1,000人、コンバージョン数50件;グループB:1,000人、コンバージョン数80件)。
prop.testを用いて、この差が統計的に有意であるかどうかを検定する。コーエンのdによる効果量を算出する。 -
基本演習:3×3の分割表(3つの広告チャネル × クリックの有無)を作成し、
chisq.testを使用して、チャネルとクリックが独立しているかどうかを検定してください。result$expectedを確認してください。すべての期待頻度は 5 以上ですか? -
応用演習:3つの指導法(各グループ20名)のテスト得点をシミュレートし、
aovを使用して分散分析(ANOVA)を行い、その後TukeyHSDを使用して、どの2つのグループの間に最も大きな差が見られるかを特定してください。 -
課題:完全なA/Bテストを実施してください。2つのページ(各1,000ユーザー)について、コンバージョン時間とコンバージョン率をシミュレートします。t検定、prop.test、およびコーエンのdを用いて包括的な評価を行い、意思決定レポート(p値、効果量、およびビジネス上の提言を含む)を作成してください。スクリーンショットを撮影し、保存してください。



