or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

array-operations.mdcombinatorics.mddata-manipulation.mddescriptive-statistics.mddistributions.mdindex.mdmachine-learning.mdmath-utilities.mdquantiles.mdregression.mdtesting.md

quantiles.mddocs/

0

# Quantiles and Ranges

1

2

Functions for calculating percentiles, quartiles, and range statistics.

3

4

## Core Imports

5

6

```typescript

7

import {

8

quantile,

9

quantileSorted,

10

quantileRank,

11

quantileRankSorted,

12

interquartileRange,

13

medianAbsoluteDeviation,

14

min,

15

max,

16

extent,

17

minSorted,

18

maxSorted,

19

extentSorted

20

} from "simple-statistics";

21

```

22

23

## Quantile Functions

24

25

### quantile { .api }

26

27

```typescript { .api }

28

function quantile(values: number[], p: number): number;

29

function quantile(values: number[], p: number[]): number[];

30

```

31

32

Calculates quantiles (percentiles) from a dataset. Automatically sorts the data.

33

34

**Parameters:**

35

- `values: number[]` - Array of numeric values

36

- `p: number | number[]` - Quantile(s) to calculate (0-1 range)

37

38

**Returns:** `number | number[]` - Quantile value(s)

39

40

**Common Quantiles:**

41

- 0.25 = 25th percentile (Q1)

42

- 0.50 = 50th percentile (median, Q2)

43

- 0.75 = 75th percentile (Q3)

44

45

```typescript

46

import { quantile } from "simple-statistics";

47

48

const testScores = [65, 70, 75, 80, 85, 90, 95];

49

50

// Single quantile

51

const median = quantile(testScores, 0.5); // 80

52

const q1 = quantile(testScores, 0.25); // 70

53

const q3 = quantile(testScores, 0.75); // 90

54

55

// Multiple quantiles at once

56

const quartiles = quantile(testScores, [0.25, 0.5, 0.75]);

57

// [70, 80, 90]

58

59

console.log(`Q1: ${q1}, Median: ${median}, Q3: ${q3}`);

60

```

61

62

### quantileSorted { .api }

63

64

```typescript { .api }

65

function quantileSorted(values: number[], p: number): number;

66

function quantileSorted(values: number[], p: number[]): number[];

67

```

68

69

Optimized quantile calculation for pre-sorted arrays.

70

71

**Parameters:**

72

- `values: number[]` - Pre-sorted array of numeric values

73

- `p: number | number[]` - Quantile(s) to calculate (0-1 range)

74

75

**Returns:** `number | number[]` - Quantile value(s)

76

77

```typescript

78

import { quantileSorted } from "simple-statistics";

79

80

// Data must be pre-sorted

81

const sortedScores = [65, 70, 75, 80, 85, 90, 95];

82

const percentiles = quantileSorted(sortedScores, [0.1, 0.5, 0.9]);

83

// [67, 80, 93] - 10th, 50th, 90th percentiles

84

```

85

86

## Quantile Ranks

87

88

### quantileRank { .api }

89

90

```typescript { .api }

91

function quantileRank(values: number[], value: number): number;

92

```

93

94

Calculates what percentile a specific value represents in the dataset.

95

96

**Parameters:**

97

- `values: number[]` - Array of numeric values

98

- `value: number` - Value to find the rank for

99

100

**Returns:** `number` - Quantile rank (0-1 range)

101

102

```typescript

103

import { quantileRank } from "simple-statistics";

104

105

const classScores = [60, 65, 70, 75, 80, 85, 90, 95];

106

const studentScore = 80;

107

108

const rank = quantileRank(classScores, studentScore); // 0.625

109

const percentile = Math.round(rank * 100); // 63rd percentile

110

111

console.log(`Score of ${studentScore} is at the ${percentile}th percentile`);

112

```

113

114

### quantileRankSorted { .api }

115

116

```typescript { .api }

117

function quantileRankSorted(values: number[], value: number): number;

118

```

119

120

Optimized quantile rank calculation for pre-sorted arrays.

121

122

## Range Statistics

123

124

### interquartileRange (alias: iqr) { .api }

125

126

```typescript { .api }

127

function interquartileRange(values: number[]): number;

128

```

129

130

Calculates the interquartile range (Q3 - Q1), a robust measure of spread.

131

132

**Parameters:**

133

- `values: number[]` - Array of numeric values

134

135

**Returns:** `number` - IQR value

136

137

**Use Cases:**

138

- Robust measure of variability (less sensitive to outliers than standard deviation)

139

- Box plot construction

140

- Outlier detection (values beyond Q1-1.5×IQR or Q3+1.5×IQR)

141

142

```typescript

143

import { interquartileRange, quantile } from "simple-statistics";

144

145

const salaries = [35000, 40000, 45000, 50000, 55000, 60000, 120000]; // One outlier

146

147

const iqr = interquartileRange(salaries); // 15000

148

const q1 = quantile(salaries, 0.25); // 42500

149

const q3 = quantile(salaries, 0.75); // 57500

150

151

console.log(`IQR: $${iqr.toLocaleString()}`);

152

console.log(`Middle 50% of salaries: $${q1.toLocaleString()} - $${q3.toLocaleString()}`);

153

154

// Outlier detection

155

const lowerFence = q1 - 1.5 * iqr; // 20000

156

const upperFence = q3 + 1.5 * iqr; // 80000

157

158

const outliers = salaries.filter(salary => salary < lowerFence || salary > upperFence);

159

console.log(`Outliers: $${outliers.map(s => s.toLocaleString()).join(', ')}`); // $120,000

160

```

161

162

### medianAbsoluteDeviation (alias: mad) { .api }

163

164

```typescript { .api }

165

function medianAbsoluteDeviation(values: number[]): number;

166

```

167

168

Calculates the median absolute deviation, another robust measure of variability.

169

170

**Parameters:**

171

- `values: number[]` - Array of numeric values

172

173

**Returns:** `number` - MAD value

174

175

**Formula:** MAD = median(|xi - median(x)|)

176

177

```typescript

178

import { medianAbsoluteDeviation, median } from "simple-statistics";

179

180

const responseTime = [120, 125, 130, 135, 200]; // One slow response

181

182

const medianTime = median(responseTime); // 130ms

183

const mad = medianAbsoluteDeviation(responseTime); // 5ms

184

185

console.log(`Median response: ${medianTime}ms`);

186

console.log(`MAD: ${mad}ms`);

187

// MAD is less affected by the 200ms outlier than standard deviation would be

188

```

189

190

## Min/Max and Extent

191

192

### min { .api }

193

194

```typescript { .api }

195

function min(values: number[]): number;

196

```

197

198

Finds the minimum value in an array.

199

200

### max { .api }

201

202

```typescript { .api }

203

function max(values: number[]): number;

204

```

205

206

Finds the maximum value in an array.

207

208

### extent { .api }

209

210

```typescript { .api }

211

function extent(values: number[]): [number, number];

212

```

213

214

Returns both minimum and maximum as a tuple.

215

216

**Parameters:**

217

- `values: number[]` - Array of numeric values

218

219

**Returns:** `[number, number]` - Tuple containing [minimum, maximum]

220

221

```typescript

222

import { min, max, extent } from "simple-statistics";

223

224

const temperatures = [-5, 0, 12, 18, 25, 30];

225

226

const minTemp = min(temperatures); // -5

227

const maxTemp = max(temperatures); // 30

228

const tempRange = extent(temperatures); // [-5, 30]

229

230

console.log(`Temperature range: ${tempRange[0]}°C to ${tempRange[1]}°C`);

231

console.log(`Temperature span: ${tempRange[1] - tempRange[0]}°C`);

232

```

233

234

### Sorted Array Optimizations

235

236

For pre-sorted arrays, use these optimized versions:

237

238

```typescript { .api }

239

function minSorted(values: number[]): number;

240

function maxSorted(values: number[]): number;

241

function extentSorted(values: number[]): [number, number];

242

```

243

244

Optimized extent calculation for pre-sorted arrays.

245

246

**Parameters:**

247

- `values: number[]` - Pre-sorted array of numeric values

248

249

**Returns:** `[number, number]` - Tuple containing [minimum, maximum]

250

251

```typescript

252

import { minSorted, maxSorted, extentSorted } from "simple-statistics";

253

254

// Pre-sorted data

255

const sortedPrices = [9.99, 12.50, 15.75, 22.00, 35.99];

256

257

const cheapest = minSorted(sortedPrices); // 9.99

258

const mostExpensive = maxSorted(sortedPrices); // 35.99

259

const priceRange = extentSorted(sortedPrices); // [9.99, 35.99]

260

```

261

262

## Usage Examples

263

264

### Performance Analysis Dashboard

265

266

```typescript

267

import { quantile, interquartileRange, quantileRank } from "simple-statistics";

268

269

// Website response times (ms)

270

const responseTimes = [

271

45, 52, 48, 67, 55, 50, 47, 53, 49, 51, 46, 54, 48, 52, 50,

272

49, 47, 53, 51, 48, 50, 65, 58, 44, 56, 49, 52, 47, 53, 150 // One slow outlier

273

];

274

275

// Calculate performance metrics

276

const percentiles = quantile(responseTimes, [0.5, 0.95, 0.99]);

277

const [median, p95, p99] = percentiles;

278

279

const iqr = interquartileRange(responseTimes);

280

const slaThreshold = 100; // 100ms SLA

281

const slaPercentile = quantileRank(responseTimes, slaThreshold);

282

283

console.log("Performance Dashboard:");

284

console.log(`Median response time: ${median}ms`);

285

console.log(`95th percentile: ${p95}ms`);

286

console.log(`99th percentile: ${p99}ms`);

287

console.log(`IQR: ${iqr}ms`);

288

console.log(`SLA compliance: ${(slaPercentile * 100).toFixed(1)}% under ${slaThreshold}ms`);

289

290

// Alerting based on percentiles

291

if (p95 > 80) {

292

console.log("🚨 Alert: 95th percentile exceeds 80ms threshold");

293

}

294

```

295

296

### Salary Band Analysis

297

298

```typescript

299

import { quantile, quantileRank, interquartileRange } from "simple-statistics";

300

301

// Company salary data

302

const salaries = [

303

45000, 48000, 52000, 55000, 58000, 62000, 65000, 68000, 72000, 75000,

304

78000, 82000, 85000, 90000, 95000, 100000, 110000, 120000, 150000, 200000

305

];

306

307

// Define salary bands using quartiles

308

const salaryBands = quantile(salaries, [0.25, 0.5, 0.75]);

309

const [q1, median, q3] = salaryBands;

310

311

console.log("Salary Band Analysis:");

312

console.log(`Entry Level (0-25th): Up to $${q1.toLocaleString()}`);

313

console.log(`Mid Level (25-50th): $${q1.toLocaleString()} - $${median.toLocaleString()}`);

314

console.log(`Senior Level (50-75th): $${median.toLocaleString()} - $${q3.toLocaleString()}`);

315

console.log(`Executive (75th+): $${q3.toLocaleString()}+`);

316

317

// Individual salary analysis

318

const candidateSalary = 87000;

319

const candidatePercentile = quantileRank(salaries, candidateSalary);

320

321

console.log(`\nCandidate Analysis:`);

322

console.log(`Salary: $${candidateSalary.toLocaleString()}`);

323

console.log(`Percentile: ${Math.round(candidatePercentile * 100)}th`);

324

325

if (candidatePercentile > 0.75) {

326

console.log("Band: Executive Level");

327

} else if (candidatePercentile > 0.5) {

328

console.log("Band: Senior Level");

329

} else if (candidatePercentile > 0.25) {

330

console.log("Band: Mid Level");

331

} else {

332

console.log("Band: Entry Level");

333

}

334

```

335

336

### Outlier Detection

337

338

```typescript

339

import { quantile, interquartileRange, medianAbsoluteDeviation } from "simple-statistics";

340

341

// Stock price changes (%)

342

const priceChanges = [

343

-2.1, -1.5, -0.8, 0.2, 0.5, 1.2, 1.8, 2.3, -1.2, 0.8,

344

1.5, -0.5, 2.1, -1.8, 0.3, 1.1, -15.2, 2.5, -0.9, 1.7 // -15.2% is outlier

345

];

346

347

// IQR method for outlier detection

348

const [q1, q3] = quantile(priceChanges, [0.25, 0.75]);

349

const iqr = interquartileRange(priceChanges);

350

const lowerFence = q1 - 1.5 * iqr;

351

const upperFence = q3 + 1.5 * iqr;

352

353

const iqrOutliers = priceChanges.filter(change =>

354

change < lowerFence || change > upperFence

355

);

356

357

// MAD method for outlier detection (more robust)

358

const mad = medianAbsoluteDeviation(priceChanges);

359

const median = quantile(priceChanges, 0.5);

360

const madThreshold = 3; // 3 MADs from median

361

362

const madOutliers = priceChanges.filter(change =>

363

Math.abs(change - median) > madThreshold * mad

364

);

365

366

console.log("Outlier Detection Results:");

367

console.log(`IQR method: ${iqrOutliers.length} outliers: ${iqrOutliers.map(x => x.toFixed(1)).join(', ')}%`);

368

console.log(`MAD method: ${madOutliers.length} outliers: ${madOutliers.map(x => x.toFixed(1)).join(', ')}%`);

369

console.log(`Normal range (IQR): ${lowerFence.toFixed(1)}% to ${upperFence.toFixed(1)}%`);

370

```