Skip to content

Quantiles and Percentiles Examples ​

Examples of working with quantiles, percentiles, and quartiles in @addmaple/stats.

Percentiles ​

Basic Percentile Calculation ​

js
import { init, percentile } from '@addmaple/stats';

await init();

const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// 50th percentile (median)
const median = percentile(data, 0.5);
console.log(median); // 5.5

// 90th percentile
const p90 = percentile(data, 0.9);
console.log(p90); // 9.1

// 25th percentile (Q1)
const q1 = percentile(data, 0.25);
console.log(q1); // 3.25

Exclusive vs Inclusive Method ​

js
import { init, percentile } from '@addmaple/stats';

await init();

const data = [1, 2, 3, 4, 5];

// Inclusive method (default, R7)
const inclusive = percentile(data, 0.5, false);
console.log(inclusive); // 3

// Exclusive method (R6)
const exclusive = percentile(data, 0.5, true);
console.log(exclusive); // 3

Real-World Example: Test Scores ​

js
import { init, percentile } from '@addmaple/stats';

await init();

const scores = [65, 72, 78, 82, 85, 88, 90, 92, 95, 98];

// What score is at the 75th percentile?
const p75 = percentile(scores, 0.75);
console.log(`75th percentile: ${p75}`); // ~92

// What score is at the 25th percentile?
const p25 = percentile(scores, 0.25);
console.log(`25th percentile: ${p25}`); // ~78

Quartiles ​

Basic Quartile Calculation ​

js
import { init, quartiles } from '@addmaple/stats';

await init();

const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const { q1, q2, q3 } = quartiles(data);
console.log(`Q1: ${q1}`); // 3.25
console.log(`Q2 (median): ${q2}`); // 5.5
console.log(`Q3: ${q3}`); // 7.75

Interquartile Range (IQR) ​

js
import { init, quartiles, iqr } from '@addmaple/stats';

await init();

const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Calculate IQR directly
const range = iqr(data);
console.log(`IQR: ${range}`); // 4.5

// Or calculate from quartiles
const { q1, q3 } = quartiles(data);
const manualIqr = q3 - q1;
console.log(`Manual IQR: ${manualIqr}`); // 4.5

Outlier Detection Using IQR ​

js
import { init, quartiles, iqr } from '@addmaple/stats';

await init();

const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 50]; // 50 is an outlier

const { q1, q3 } = quartiles(data);
const iqrValue = iqr(data);

const lowerBound = q1 - 1.5 * iqrValue;
const upperBound = q3 + 1.5 * iqrValue;

const outliers = data.filter(x => x < lowerBound || x > upperBound);
console.log('Outliers:', outliers); // [50]

Multiple Quantiles ​

Calculate Multiple Quantiles at Once ​

js
import { init, quantiles } from '@addmaple/stats';

await init();

const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Calculate deciles (10th, 20th, ..., 90th percentiles)
const deciles = [];
for (let i = 1; i < 10; i++) {
  deciles.push(i / 10);
}

const decileValues = quantiles(data, deciles);
console.log('Deciles:', decileValues);
// Float64Array [1.9, 2.8, 3.7, 4.6, 5.5, 6.4, 7.3, 8.2, 9.1]

Vectorized Percentiles Helper ​

js
import { init, percentiles } from '@addmaple/stats';

await init();

const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Request several percentiles in one call (10th, 50th, 90th)
const ps = [0.1, 0.5, 0.9];
const values = percentiles(data, ps);

console.log(values); // Float64Array [1.9, 5.5, 9.1]

Percentiles of Score ​

js
import { init, percentileOfScore } from '@addmaple/stats';

await init();

const data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];

// What percentile is score 75?
const percentile = percentileOfScore(data, 75);
console.log(`75 is at the ${percentile * 100}th percentile`); // ~70th percentile

// Strict comparison (< instead of <=)
const strict = percentileOfScore(data, 75, true);
console.log(`Strict: ${strict * 100}th percentile`);

Real-World Examples ​

Income Distribution Analysis ​

js
import { init, quartiles, iqr, percentile } from '@addmaple/stats';

await init();

const incomes = [
  25000, 30000, 35000, 40000, 45000,
  50000, 55000, 60000, 70000, 80000,
  90000, 100000, 120000, 150000, 200000
];

const { q1, q2, q3 } = quartiles(incomes);
const iqrValue = iqr(incomes);

console.log(`Median income: $${q2.toLocaleString()}`);
console.log(`Q1: $${q1.toLocaleString()}`);
console.log(`Q3: $${q3.toLocaleString()}`);
console.log(`IQR: $${iqrValue.toLocaleString()}`);

// Top 10% income
const top10 = percentile(incomes, 0.9);
console.log(`Top 10%: $${top10.toLocaleString()}`);

Test Score Analysis ​

js
import { init, percentile, quartiles } from '@addmaple/stats';

await init();

const scores = [45, 52, 58, 62, 65, 68, 72, 75, 78, 82, 85, 88, 92, 95, 98];

// Grade boundaries
const aMin = percentile(scores, 0.9); // Top 10%
const bMin = percentile(scores, 0.7); // Top 30%
const cMin = percentile(scores, 0.5); // Top 50%

console.log(`A grade: >= ${aMin}`);
console.log(`B grade: >= ${bMin}`);
console.log(`C grade: >= ${cMin}`);

// Quartiles for box plot
const { q1, q2, q3 } = quartiles(scores);
console.log(`Box plot: [${q1}, ${q2}, ${q3}]`);

Performance Metrics ​

js
import { init, percentile, quartiles } from '@addmaple/stats';

await init();

const responseTimes = [10, 12, 15, 18, 20, 22, 25, 28, 30, 35, 40, 45, 50];

// P50, P95, P99 percentiles
const p50 = percentile(responseTimes, 0.5);
const p95 = percentile(responseTimes, 0.95);
const p99 = percentile(responseTimes, 0.99);

console.log(`P50: ${p50}ms`);
console.log(`P95: ${p95}ms`);
console.log(`P99: ${p99}ms`);

// Quartiles for distribution understanding
const { q1, q2, q3 } = quartiles(responseTimes);
console.log(`Distribution: Q1=${q1}, Median=${q2}, Q3=${q3}`);

Weighted Quantiles ​

When observations have different importance or frequency weights, use weighted quantiles instead of regular quantiles. This is common in survey data, aggregated statistics, or any scenario where values represent different numbers of observations.

Basic Weighted Percentile ​

js
import { init, weightedPercentile } from '@addmaple/stats';

await init();

const values = [1, 2, 3, 4, 5];
const weights = [1, 1, 1, 1, 5]; // Value 5 has 5x more weight

// Weighted median - pulled toward 5 due to higher weight
const median = weightedPercentile(values, weights, 0.5);
console.log(`Weighted median: ${median}`); // ~4.3

// Compare with equal weights (behaves like regular percentile)
const equalWeights = [1, 1, 1, 1, 1];
const regularMedian = weightedPercentile(values, equalWeights, 0.5);
console.log(`Regular median: ${regularMedian}`); // 3

Weighted Median ​

js
import { init, weightedMedian } from '@addmaple/stats';

await init();

// Survey data: respondent ages with sampling weights
const ages = [25, 35, 45, 55, 65];
const sampleWeights = [100, 150, 200, 120, 80];

const medianAge = weightedMedian(ages, sampleWeights);
console.log(`Weighted median age: ${medianAge}`);

Multiple Weighted Quantiles ​

js
import { init, weightedQuantiles } from '@addmaple/stats';

await init();

const income = [20000, 40000, 60000, 80000, 100000];
const population = [1000, 800, 500, 300, 100]; // More people earn less

// Calculate weighted quartiles
const [q1, median, q3] = weightedQuantiles(income, population, [0.25, 0.5, 0.75]);
console.log(`Q1: $${q1.toLocaleString()}`);
console.log(`Median: $${median.toLocaleString()}`);
console.log(`Q3: $${q3.toLocaleString()}`);
// Results weighted toward lower incomes due to population distribution

Weighted Income Distribution ​

js
import { init, weightedPercentile, weightedQuantiles } from '@addmaple/stats';

await init();

// Income brackets with population counts (aggregated census data)
const incomes = [15000, 25000, 35000, 50000, 75000, 100000, 150000, 250000];
const householdCounts = [2000, 5000, 8000, 6000, 4000, 2500, 1000, 500];

// Calculate weighted percentiles
const p10 = weightedPercentile(incomes, householdCounts, 0.1);
const p50 = weightedPercentile(incomes, householdCounts, 0.5);
const p90 = weightedPercentile(incomes, householdCounts, 0.9);

console.log(`10th percentile income: $${p10.toLocaleString()}`);
console.log(`Median income: $${p50.toLocaleString()}`);
console.log(`90th percentile income: $${p90.toLocaleString()}`);

// Get all deciles at once
const decilePoints = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9];
const deciles = weightedQuantiles(incomes, householdCounts, decilePoints);
console.log('Income deciles:', Array.from(deciles).map(d => `$${d.toLocaleString()}`));

Survey Response Analysis ​

js
import { init, weightedMedian, weightedQuantiles } from '@addmaple/stats';

await init();

// Survey responses with frequency weights
// (Each response represents multiple respondents with same answer)
const satisfactionScores = [1, 2, 3, 4, 5]; // 1-5 scale
const responseFrequencies = [50, 80, 200, 150, 120]; // Number of people

const medianSatisfaction = weightedMedian(satisfactionScores, responseFrequencies);
console.log(`Median satisfaction: ${medianSatisfaction.toFixed(2)}`);

// Get quartiles for box plot
const [q1, q2, q3] = weightedQuantiles(
  satisfactionScores, 
  responseFrequencies, 
  [0.25, 0.5, 0.75]
);
console.log(`Satisfaction quartiles: Q1=${q1.toFixed(2)}, Q2=${q2.toFixed(2)}, Q3=${q3.toFixed(2)}`);