explodorama / files / tools / balance / stats.ts
stats.ts
| 1 | /** Mean and a 95% confidence interval's half-width, for paired differences and plain samples. */ |
| 2 | export interface Estimate { |
| 3 | mean: number |
| 4 | /** Half the 95% interval: the true mean is within mean ± ci, 19 times in 20. */ |
| 5 | ci: number |
| 6 | n: number |
| 7 | } |
| 8 | |
| 9 | export function estimate(xs: number[]): Estimate { |
| 10 | const n = xs.length |
| 11 | if (!n) return { mean: 0, ci: 0, n } |
| 12 | const mean = xs.reduce((a, b) => a + b, 0) / n |
| 13 | const variance = n > 1 ? xs.reduce((a, x) => a + (x - mean) ** 2, 0) / (n - 1) : 0 |
| 14 | return { mean, ci: 1.96 * Math.sqrt(variance / n), n } |
| 15 | } |
| 16 | |
| 17 | /** "+1.2 ± 0.3", or "+1.2 ± 0.3 ✱" when the interval leaves out 0 (a real difference). */ |
| 18 | export function signed(e: Estimate, digits = 2): string { |
| 19 | const sign = e.mean > 0 ? '+' : e.mean < 0 ? '−' : ' ' |
| 20 | const real = e.n > 1 && Math.abs(e.mean) > e.ci ? ' ✱' : '' |
| 21 | return `${sign}${Math.abs(e.mean).toFixed(digits)} ± ${e.ci.toFixed(digits)}${real}` |
| 22 | } |