gleam_stats/stats

A module containing several helpful functions for computing and working with statistics.


Types

A type used to represent the bins in a histogram. The type is an alias of a tuple containing a min/max range and a count of the values in that range.

Example:
 import gleeunit/should
 import gleam/pair
 import gleam_stats/math

 pub fn example () {
   // Create a bin
   let bin: math.Bin = tuple(math.Range(0., 1.), 999)
   // Retrieve min and max values
   let math.Range(min, max) = pair.first(bin)
   min
   |> should.equal(0.)
   max
   |> should.equal(1.)
   // Retrieve count
   let count = pair.second(bin)
   count
   |> should.equal(999)
 }
pub type Bin =
  #(Range, Int)

A type used to represent a min/max interval. The Range type is among others used to represent the bin boundaries in a histogram.

Example:
 import gleam_stats/math
 import gleeunit/should

 pub fn example () {
   // Create a range
   let range = math.Range(0., 1.)
   // Retrieve min and max values
   let math.Range(min, max) = range
   min
   |> should.equal(0.)
   max
   |> should.equal(1.)
 }
pub type Range {
  Range(min: Float, max: Float)
}

Constructors

  • Range(min: Float, max: Float)

Functions

pub fn allclose(xarr: List(Float), yarr: List(Float), rtol: Float, atol: Float) -> Result(
  List(Bool),
  Nil,
)

Determine if a list of values are close to or equivalent to a another list of reference values.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   let val: Float = 99.
   let ref_val: Float = 100.
   let xarr: List(Float) = list.repeat(val, 42)
   let yarr: List(Float) = list.repeat(ref_val, 42)
   // We set 'atol' and 'rtol' such that the values are equivalent
   // if 'val' is within 1 percent of 'ref_val' +/- 0.1
   let rtol: Float = 0.01
   let atol: Float = 0.10
   math.allclose(xarr, yarr, rtol, atol)
   |> fn(zarr: Result(List(Bool), Nil)) -> Result(Bool, Nil) {
     case zarr {
       Ok(arr) ->
         arr
         |> list.all(fn(a: Bool) -> Bool { a })
         |> Ok()
       _ -> Error(Nil)
     }
   }
   |> should.equal(Ok(True))
 }
pub fn amax(arr: List(Float)) -> Result(Float, Nil)

Returns the maximum value of a list.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   |> math.amax()
   |> should.equal(Error(Nil))
 
   [4., 4., 3., 2., 1.]
   |> math.amax()
   |> should.equal(Ok(4.))
 }
pub fn amin(arr: List(Float)) -> Result(Float, Nil)

Returns the minimum value of a list.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   |> math.amin()
   |> should.equal(Error(Nil))
 
   [4., 4., 3., 2., 1.]
   |> math.amin()
   |> should.equal(Ok(1.))
 }
pub fn argmax(arr: List(Float)) -> Result(List(Int), Nil)

Returns the indices of the maximum values in a list.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   |> math.argmax()
   |> should.equal(Error(Nil))
 
   [4., 4., 3., 2., 1.]
   |> math.argmax()
   |> should.equal(Ok([0, 1]))
 }
pub fn argmin(arr: List(Float)) -> Result(List(Int), Nil)

Returns the indices of the minimum values in a list.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   |> math.argmin()
   |> should.equal(Error(Nil))
 
   [4., 4., 3., 2., 1.]
   |> math.argmin()
   |> should.equal(Ok([4]))
 }
pub fn correlation(xarr: List(Float), yarr: List(Float)) -> Result(
  Float,
  Nil,
)

Calculate the Pearson correlation coefficient to determine the linear relationship between the elements in two lists of equal length.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   math.correlation([], [])
   |> should.equal(Error(Nil))
 
   // Perfect positive correlation
   let xarr0: List(Float) =
     list.range(0, 100)
     |> list.map(fn(x: Int) -> Float { int.to_float(x) })
   let yarr0: List(Float) =
     list.range(0, 100)
     |> list.map(fn(x: Int) -> Float { int.to_float(x) })
   math.correlation(xarr0, yarr0)
   |> should.equal(Ok(1.))
 
   // Perfect negative correlation
   let xarr0: List(Float) =
     list.range(0, 100)
     |> list.map(fn(x: Int) -> Float { -1. *. int.to_float(x) })
   let yarr0: List(Float) =
     list.range(0, 100)
     |> list.map(fn(x: Int) -> Float { int.to_float(x) })
   math.correlation(xarr0, yarr0)
   |> should.equal(Ok(-1.))
 }
pub fn freedman_diaconis_rule(arr: List(Float)) -> Result(
  Float,
  Nil,
)

Use Freedman-Diaconis’s Rule to determine the bin widths of a histogram.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   |> math.freedman_diaconis_rule()
   |> should.equal(Error(Nil))
 
   // Calculate histogram bin widths
   list.range(0, 1000)
   |> list.map(fn(x: Int) -> Float { int.to_float(x) })
   |> math.freedman_diaconis_rule()
   |> should.equal(Ok(10.))
 }
pub fn gmean(arr: List(Float)) -> Result(Float, Nil)

Calculcate the geometric mean of the elements in a list. Note that the geometric mean is only defined for positive numbers.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   |> math.gmean()
   |> should.equal(Error(Nil))
 
   [1., 3., 9.]
   |> math.gmean()
   |> should.equal(Ok(3.))
 }
pub fn histogram(arr: List(Float), width: Float) -> Result(
  List(#(Range, Int)),
  Nil,
)

Create a histogram of the elements in a list.

Example:
 import gleam_stats/math
 import gleeunit/should

 pub fn example () {
   list.range(0, 100)
   |> list.map(fn(x: Int) -> Float { int.to_float(x) })
   // Below 25. is the bin width
   // The Freedman-Diaconis’s Rule can be used to determine a decent value
   |> math.histogram(25.)
   |> should.equal(Ok([
     tuple(math.Range(0., 25.), 25),
     tuple(math.Range(25., 50.), 25),
     tuple(math.Range(50., 75.), 25),
     tuple(math.Range(75., 100.), 25),
   ]))

   []
   |> math.histogram(1.)
   |> should.equal(Error(Nil))
 }
pub fn hmean(arr: List(Float)) -> Result(Float, Nil)

Calculcate the harmonic mean of the elements in a list. Note that the harmonic mean is only defined for positive numbers.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   |> math.hmean()
   |> should.equal(Error(Nil))
 
   [1., 3., 6.]
   |> math.hmean()
   |> should.equal(Ok(2.))
 }
pub fn iqr(arr: List(Float)) -> Result(Float, Nil)

Calculate the interquartile range (IQR) of the elements in a list.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   |> math.iqr()
   |> should.equal(Error(Nil))
 
   [1., 2., 3., 4., 5.]
   |> math.iqr()
   |> should.equal(Ok(3.))
 }
pub fn isclose(a: Float, b: Float, rtol: Float, atol: Float) -> Bool

Determine if a given value is close to or equivalent to a reference value based on supplied relative and absolute tolerance values. The equivalance of the two given values are then determined based on the equation:

absolute(a - b) <= (atol + rtol * absolute(b))
Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   let val: Float = 99.
   let ref_val: Float = 100.
   // We set 'atol' and 'rtol' such that the values are equivalent
   // if 'val' is within 1 percent of 'ref_val' +/- 0.1
   let rtol: Float = 0.01
   let atol: Float = 0.10
   math.isclose(val, ref_val, rtol, atol)
   |> should.be_true()
 }
pub fn kurtosis(arr: List(Float)) -> Result(Float, Nil)

Calculcate the sample kurtosis of a list of elements using the definition of Fisher.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   |> math.skewness()
   |> should.equal(Error(Nil))
 
   // No tail 
   // -> Fisher's definition gives kurtosis -3 
   [1., 1., 1., 1.]
   |> math.kurtosis()
   |> should.equal(Ok(-3.))
 
   // Distribution with a tail 
   // -> Higher kurtosis 
   [1., 1., 1., 2.]
   |> math.kurtosis()
   |> fn(x: Result(Float, Nil)) -> Bool {
     case x {
       Ok(x) -> x >. -3.
     }
   }
   |> should.be_true()
 }
pub fn mean(arr: List(Float)) -> Result(Float, Nil)

Calculcate the arithmetic mean of the elements in a list.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   |> math.mean()
   |> should.equal(Error(Nil))
 
   [1., 2., 3.]
   |> math.mean()
   |> should.equal(Ok(2.))
 }
pub fn median(arr: List(Float)) -> Result(Float, Nil)

Calculcate the median of the elements in a list.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   |> math.median()
   |> should.equal(Error(Nil))
 
   [1., 2., 3.]
   |> math.median()
   |> should.equal(Ok(2.))
 
   [1., 2., 3., 4.]
   |> math.median()
   |> should.equal(Ok(2.5))
 }
pub fn moment(arr: List(Float), n: Int) -> Result(Float, Nil)

Calculcate the n’th moment about the mean of a list of elements.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   |> math.moment(0)
   |> should.equal(Error(Nil))
 
   // 0th moment about the mean is 1. per definition
   [0., 1., 2., 3., 4.]
   |> math.moment(0)
   |> should.equal(Ok(1.))
 
   // 1st moment about the mean is 0. per definition
   [0., 1., 2., 3., 4.]
   |> math.moment(1)
   |> should.equal(Ok(0.))
 
   [0., 1., 2., 3., 4.]
   |> math.moment(2)
   |> should.equal(Ok(2.))
 }
pub fn percentile(arr: List(Float), n: Int) -> Result(Float, Nil)

Calculate the n’th percentile of the elements in a list using linear interpolation between closest ranks.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   |> math.percentile(40)
   |> should.equal(Error(Nil))
 
   // Calculate 40th percentile 
   [15., 20., 35., 40., 50.]
   |> math.percentile(40)
   |> should.equal(Ok(29.))
 }
pub fn skewness(arr: List(Float)) -> Result(Float, Nil)

Calculcate the sample skewness of a list of elements using the Fisher-Pearson coefficient of skewness.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   |> math.skewness()
   |> should.equal(Error(Nil))
 
   // No skewness 
   // -> Zero skewness
   [1., 2., 3., 4.]
   |> math.skewness()
   |> should.equal(Ok(0.))
 
   // Right-skewed distribution 
   // -> Positive skewness
   [1., 1., 1., 2.]
   |> math.skewness()
   |> fn(x: Result(Float, Nil)) -> Bool {
     case x {
       Ok(x) -> x >. 0.
     }
   }
   |> should.be_true()
 }
pub fn std(arr: List(Float), ddof: Int) -> Result(Float, Nil)

Calculcate the sample standard deviation of the elements in a list.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   // Degrees of freedom
   let ddof: Int = 1
 
   []
   |> math.std(ddof)
   |> should.equal(Error(Nil))
 
   [1., 2., 3.]
   |> math.std(ddof)
   |> should.equal(Ok(1.))
 }
pub fn sum(arr: List(Float)) -> Float

Calculcate the sum of the elements in a list.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   |> math.sum()
   |> should.equal(0.)
 
   [1., 2., 3.]
   |> math.sum()
   |> should.equal(6.)
 }
pub fn trim(arr: List(Float), min: Int, max: Int) -> Result(
  List(Float),
  Nil,
)

Trim a list to a certain size given min/max indices. The min/max indices are inclusive.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   |> math.trim(0, 0)
   |> should.equal(Error(Nil))
 
   // Trim list to only middle part of list
   [1., 2., 3., 4., 5., 6.]
   |> math.trim(1, 4)
   |> should.equal(Ok([2., 3., 4., 5.]))
 }
pub fn var(arr: List(Float), ddof: Int) -> Result(Float, Nil)

Calculcate the sample variance of the elements in a list.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   // Degrees of freedom
   let ddof: Int = 1
 
   []
   |> math.var(ddof)
   |> should.equal(Error(Nil))
 
   [1., 2., 3.]
   |> math.var(ddof)
   |> should.equal(Ok(1.))
 }
pub fn zscore(arr: List(Float), ddof: Int) -> Result(
  List(Float),
  Nil,
)

Calculate the z-score of each value in the list relative to the sample mean and standard deviation.

Example:
 import gleeunit/should
 import gleam_stats/math

 pub fn example () {
   []
   // Use degrees of freedom = 1
   |> math.zscore(1)
   |> should.equal(Error(Nil))
 
   [1., 2., 3.]
   // Use degrees of freedom = 1
   |> math.zscore(1)
   |> should.equal(Ok([-1., 0., 1.]))
 }