Module: SkiftetStatistical::Descriptive

Defined in:
lib/skiftet_statistical/descriptive.rb

Overview

Descriptive statistics over a collection of numbers — mean, variance, standard deviation, and interpolated percentiles. Consolidates the ad-hoc mean/variance (skram.la's revenue-per-visitor stats) and percentile logic (ekonomidata.nu's income distributions) scattered across the workspace.

Class Method Summary collapse

Class Method Details

.mean(values) ⇒ Object

Arithmetic mean (0.0 for an empty collection).



12
13
14
15
16
# File 'lib/skiftet_statistical/descriptive.rb', line 12

def mean(values)
  return 0.0 if values.empty?

  values.sum.to_f / values.length
end

.median(values) ⇒ Object



50
51
52
# File 'lib/skiftet_statistical/descriptive.rb', line 50

def median(values)
  percentile(values, 50)
end

.percentile(values, p) ⇒ Object

Linear-interpolation percentile, p in [0, 100]. nil for an empty collection. percentile(values, 50) == median.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/skiftet_statistical/descriptive.rb', line 35

def percentile(values, p)
  return nil if values.empty?

  sorted = values.sort
  return sorted.first.to_f if sorted.length == 1

  rank = (p.clamp(0, 100) / 100.0) * (sorted.length - 1)
  lower = rank.floor
  upper = rank.ceil
  return sorted[lower].to_f if lower == upper

  weight = rank - lower
  (sorted[lower] * (1.0 - weight)) + (sorted[upper] * weight)
end

.standard_deviation(values, sample: true) ⇒ Object



29
30
31
# File 'lib/skiftet_statistical/descriptive.rb', line 29

def standard_deviation(values, sample: true)
  Math.sqrt(variance(values, sample: sample))
end

.variance(values, sample: true) ⇒ Object

Variance. sample: true (default) divides by n-1 (Bessel's correction); sample: false divides by n (population variance). 0.0 for n < 2.



20
21
22
23
24
25
26
27
# File 'lib/skiftet_statistical/descriptive.rb', line 20

def variance(values, sample: true)
  n = values.length
  return 0.0 if n < 2

  m = mean(values)
  ss = values.sum { |v| (v - m)**2 }
  ss / (sample ? (n - 1) : n).to_f
end