///|
pub struct Histogram {
edges : Array[Double]
counts : Array[Int]
} derive(Debug, Eq)
///|
pub struct LinearRegression {
slope : Double
intercept : Double
r_squared : Double
} derive(Debug, Eq)
///|
pub fn histogram(
values : Array[Double],
lower : Double,
upper : Double,
bins : Int,
) -> Histogram {
let count = bins.max(1)
let edges : Array[Double] = []
let counts : Array[Int] = []
for i in 0..<=count {
edges.push(
lerp_scalar(lower, upper, Double::from_int(i) / Double::from_int(count)),
)
}
for _ in 0.. 0.0 {
for value in values {
let index = ((value - lower) / width)
.floor()
.to_int()
.min(count - 1)
.max(0)
counts[index] += 1
}
}
{ edges, counts }
}
///|
pub fn percentile(values : Array[Double], fraction : Double) -> Double {
if values.length() == 0 {
0.0
} else {
let sorted = values.copy()
for i in 0.. Double {
if xs.length() != ys.length() || xs.length() < 2 {
0.0
} else {
let ax = mean(xs)
let ay = mean(ys)
let mut total = 0.0
for i in 0.. Double {
let denominator = variance(xs).sqrt() * variance(ys).sqrt()
if denominator == 0.0 {
0.0
} else {
covariance(xs, ys) / denominator
}
}
///|
pub fn linear_regression(
xs : Array[Double],
ys : Array[Double],
) -> LinearRegression {
let slope = if variance(xs) == 0.0 {
0.0
} else {
covariance(xs, ys) / variance(xs)
}
let intercept = mean(ys) - slope * mean(xs)
let predicted = xs.map(x => slope * x + intercept)
let total = ys.fold(init=0.0, (sum, y) => {
sum + (y - mean(ys)) * (y - mean(ys))
})
let mut residual = 0.0
for i in 0.. Double {
let deviation = variance(values).sqrt()
if deviation == 0.0 {
0.0
} else {
(value - mean(values)) / deviation
}
}
///|
pub fn outliers(values : Array[Double], threshold : Double) -> Array[Double] {
let average = mean(values)
let deviation = variance(values).sqrt()
if deviation == 0.0 {
[]
} else {
values.filter(value => (value - average).abs() > threshold * deviation)
}
}
///|
pub fn cumulative_sum(values : Array[Double]) -> Array[Double] {
let result : Array[Double] = []
let mut total = 0.0
for value in values {
total += value
result.push(total)
}
result
}
///|
pub fn cumulative_maximum(values : Array[Double]) -> Array[Double] {
let result : Array[Double] = []
let mut maximum = -1.0e300
for value in values {
maximum = maximum.max(value)
result.push(maximum)
}
result
}
///|
pub fn normalize_series(values : Array[Double]) -> Array[Double] {
let stats = summarize_samples(values)
if stats.maximum == stats.minimum {
values.map(_ => 0.0)
} else {
values.map(value => inverse_lerp(stats.minimum, stats.maximum, value))
}
}