Compute the chi-square statistic: χ² = Σ (obs − exp)² / exp, summed over k categories. A single loop accumulates the per-category contributions using a diff intermediate. Library: scipy.stats.chisquare(observed, f_exp=expected) — snapshot shows statistic + pvalue; RESULT is the statistic only, matching .statistic. Observed and expected must share the same total.

By hand

4 categories, observed=[6,14,10,10] (total=40), expected=[10,10,10,10] (uniform, total=40). Per-category: (6−10)²/10=1.6, (14−10)²/10=1.6, (10−10)²/10=0, (10−10)²/10=0. χ² = 1.6+1.6+0+0 = 3.2.

naive.py
Replay: real traced execution (multi-file project)
observed = [6, 14, 10, 10]
expected = [10, 10, 10, 10]
k = len(observed)
chi2 = 0.0
for i in range(k):
    diff = observed[i] - expected[i]
    chi2 = chi2 + diff * diff / expected[i]
print('RESULT:', round(chi2, 4))
  1. observed ← [6, 14, 10, 10]

    1observed = [6, 14, 10, 10]2expected = [10, 10, 10, 10]
    values this step[6, 14, 10, 10]observed
  2. expected ← [10, 10, 10, 10]

    1observed = [6, 14, 10, 10]2expected = [10, 10, 10, 10]3k = len(observed)
    values this step[10, 10, 10, 10]expected
  3. k ← 4

    2expected = [10, 10, 10, 10]3k = len(observed)4chi2 = 0.0
    values this step4k
  4. chi2 ← 0.0

    3k = len(observed)4chi2 = 0.05for i in range(k):
    values this step0.0chi2
  5. i ← 0

    4chi2 = 0.05for i in range(k):6    diff = observed[i] - expected[i]
    values this step0i
  6. diff ← -4

    5for i in range(k):6    diff = observed[i] - expected[i]7    chi2 = chi2 + diff * diff / expected[i]
    values this step-4diff
  7. chi2 ← 1.6

    6    diff = observed[i] - expected[i]7    chi2 = chi2 + diff * diff / expected[i]8print('RESULT:', round(chi2, 4))
    values this step0.0 1.6chi2
  8. i ← 1

    4chi2 = 0.05for i in range(k):6    diff = observed[i] - expected[i]
    values this step0 1i
  9. diff ← 4

    5for i in range(k):6    diff = observed[i] - expected[i]7    chi2 = chi2 + diff * diff / expected[i]
    values this step-4 4diff
  10. chi2 ← 3.2

    6    diff = observed[i] - expected[i]7    chi2 = chi2 + diff * diff / expected[i]8print('RESULT:', round(chi2, 4))
    values this step1.6 3.2chi2
  11. i ← 2

    4chi2 = 0.05for i in range(k):6    diff = observed[i] - expected[i]
    values this step1 2i
  12. diff ← 0

    5for i in range(k):6    diff = observed[i] - expected[i]7    chi2 = chi2 + diff * diff / expected[i]
    values this step4 0diff
  13. chi2 = chi2 + diff * diff / expected[i]

    6    diff = observed[i] - expected[i]7    chi2 = chi2 + diff * diff / expected[i]8print('RESULT:', round(chi2, 4))
  14. i ← 3

    4chi2 = 0.05for i in range(k):6    diff = observed[i] - expected[i]
    values this step2 3i
  15. diff = observed[i] - expected[i]

    5for i in range(k):6    diff = observed[i] - expected[i]7    chi2 = chi2 + diff * diff / expected[i]
  16. chi2 = chi2 + diff * diff / expected[i]

    6    diff = observed[i] - expected[i]7    chi2 = chi2 + diff * diff / expected[i]8print('RESULT:', round(chi2, 4))
  17. for i in range(k):

    4chi2 = 0.05for i in range(k):6    diff = observed[i] - expected[i]
  18. stdout ← RESULT: 3.2

    7    chi2 = chi2 + diff * diff / expected[i]8print('RESULT:', round(chi2, 4))
    values this stepRESULT: 3.2stdout

With the library

scipy.stats.chisquare(observed, f_exp=expected) returns statistic and pvalue (df=k−1=3). The snapshot shows both; RESULT is the statistic.

library.py
from scipy import stats
from dalib.display import set_display
set_display()

observed = [6, 14, 10, 10]
expected = [10, 10, 10, 10]
result = stats.chisquare(observed, f_exp=expected)
print('statistic:', round(float(result.statistic), 4))
print('pvalue:', round(float(result.pvalue), 4))
print('RESULT:', round(float(result.statistic), 4))
statistic: 3.2
pvalue: 0.3618
RESULT: 3.2

Honesty

This lesson shows the computation exactly, on a tiny pinned sample. The arithmetic is correct and reproducible, but with a sample this small the result is not a valid statistical finding — it demonstrates the mechanism, not evidence. Real inference needs an adequate sample size and assumption checks (e.g. independence and expected counts ≥ 5 per cell); the p-value / interval here should be read as "how the formula is computed," not as a conclusion about a population.

Implementation notes

  • Design rule §7: RESULT = statistic only; p-value is snapshot-only.
  • df = k−1 = 3 (one degree of freedom lost because observed counts sum to a fixed total). Under H0 (observed follows the expected distribution), χ² follows a chi-square distribution with df=3.
  • Requirement: observed and expected must sum to the same total; if expected are proportions, scale them to counts first.
  • Valid when each expected count ≥ 5 (normal approximation to Poisson holds). Here all expected=10 ✓.
  • Cross-reference: frequency-count (data-basics) for computing raw observed counts from raw data before passing them here.