Web 開發者每天面對海量日誌、投票、調查數據,卻往往停留在「計數與百分比」的描述性統計層面。本文介紹如何將推論統計引入 Web 數據分析,以 PHP 實現卡方檢定,從樣本數據推斷總體分佈差異是否顯著,助力數據驅動決策。
描述性統計只告訴你「發生了什麼」,推論統計能回答「這是否具有統計學意義」。例如:
$$ \chi^2 = \sum \frac{(O_i - E_i)^2}{E_i} $$
<?php
class ChiSquareTest {
/**
* 卡方獨立性/適合度檢定
* @param array $observed 觀察頻次陣列 [285, 250, 215, 250]
* @param array|null $expected 期望頻次陣列,null 表示均勻分佈
* @return array ['chi2' => 值, 'df' => 自由度, 'p_value' => P值, 'significant' => 是否顯著]
*/
public static function goodnessOfFit(array $observed, array $expected = null) {
$n = array_sum($observed);
$k = count($observed);
if ($expected === null) {
$expected = array_fill(0, $k, $n / $k);
}
$chi2 = 0;
for ($i = 0; $i < $k; $i++) {
$diff = $observed[$i] - $expected[$i];
$chi2 += ($diff * $diff) / $expected[$i];
}
$df = $k - 1;
$p_value = 1 - self::chiSquareCDF($chi2, $df);
return [
'chi2' => $chi2,
'df' => $df,
'p_value' => $p_value,
'significant' => $p_value < 0.05,
'critical_05' => self::chiSquareCritical(0.05, $df),
'critical_01' => self::chiSquareCritical(0.01, $df),
];
}
// 卡方分佈累積分佈函數 (近似計算)
private static function chiSquareCDF($x, $df) {
// 使用不完全伽馬函數近似:P = γ(df/2, x/2) / Γ(df/2)
// 這裡用簡單的系列展開近似,生產環境建議用 stats_cdf_chisquare (PECL stats)
if (!function_exists('stats_cdf_chisquare')) {
return self::incompleteGamma($df / 2, $x / 2) / self::gamma($df / 2);
}
return stats_cdf_chisquare($x, $df);
}
// 簡易伽馬函數實現(Lanczos 近似)
private static function gamma($z) {
$coeff = [1.000000000190015, 76.18009172947146, -86.50532032941677,
24.01409824083091, -1.231739572450155, 0.1208650973866179e-2,
-0.5395239384953e-5];
$z -= 1;
$x = $coeff[0];
for ($i = 1; $i < count($coeff); $i++) {
$x += $coeff[$i] / ($z + $i);
}
$t = $z + count($coeff) - 1.5;
return sqrt(2 * M_PI) * pow($t, $z + 0.5) * exp(-$t) * $x;
}
private static function incompleteGamma($a, $x) {
// 簡易級數展開,僅供演示
if ($x < 0 || $a <= 0) return 0;
$sum = $term = 1 / $a;
for ($n = 1; $n < 100; $n++) {
$term *= $x / ($a + $n);
$sum += $term;
if (abs($term) < 1e-10) break;
}
return $sum * pow($x, $a) * exp(-$x);
}
// 臨界值查表(常用值)
private static function chiSquareCritical($alpha, $df) {
$table = [
1 => [0.05 => 3.841, 0.01 => 6.635],
2 => [0.05 => 5.991, 0.01 => 9.210],
3 => [0.05 => 7.815, 0.01 => 11.345],
4 => [0.05 => 9.488, 0.01 => 13.277],
5 => [0.05 => 11.070, 0.01 => 15.086],
];
return $table[$df][$alpha] ?? null;
}
}
// 使用示例:啤酒投票
$observed = [285, 250, 215, 250]; // Keiths, Olands, Schooner, Other
$result = ChiSquareTest::goodnessOfFit($observed);
echo "χ² = {$result['chi2']:.4f}\n";
echo "自由度 = {$result['df']}\n";
echo "P值 = {$result['p_value']:.6f}\n";
echo "顯著性 (α=0.05) : " . ($result['significant'] ? '顯著差異' : '無顯著差異') . "\n";
echo "臨界值 χ²₀.₀₅ = {$result['critical_05']}\n";
χ² = 9.8000
自由度 = 3
P值 = 0.0203
顯著性 (α=0.05) : 顯著差異
臨界值 χ²₀.₀₅ = 7.815
結論:拒絕虛無假設,各品牌支持度存在統計學顯著差異,Keiths 確實領先。
為理解卡方分佈形狀,可模擬多次隨機實驗:
function simulateChiSquare($trials = 300, $categories = 4, $experiments = 10000) {
$results = [];
for ($e = 0; $e < $experiments; $e++) {
$counts = array_fill(0, $categories, 0);
for ($t = 0; $t < $trials; $t++) {
$counts[random_int(0, $categories - 1)]++;
}
$chi2 = 0;
$expected = $trials / $categories;
foreach ($counts as $obs) {
$diff = $obs - $expected;
$chi2 += ($diff * $diff) / $expected;
}
$results[] = $chi2;
}
return $results;
}
// 繪製直方圖可視化分佈形狀
| 場景 | 適用檢定 | PHP 實現 |
|---|---|---|
| 分類數據頻次比較 | 卡方適合度/獨立性檢定 | 自實現 / PECL stats |
| 兩組數值均值比較 | t 檢定 | stats_ttest_* 函數 |
| 多組均值比較 | ANOVA 方差分析 | 需自實現或 R/Python 協作 |
| 相關性分析 | 皮爾遜/斯皮爾曼相關係數 | stats_correlation() |
| A/B 測試 | 比例差異檢定 / 貝葉斯檢定 | 自實現 / 專用庫 |
掌握基本推論統計,能讓 Web 開發者從「報表製造者」進化為「數據分析師」。PHP 雖非統計分析首選語言,但足以實現常見檢定邏輯。關鍵在於:正確定義假設、選擇合適檢定、解讀統計意義而非機械套用公式。