///|
pub fn winsorize(data : Array[Double], trim_percent : Double) -> Array[Double] {
if data.length() == 0 {
return []
}
if trim_percent < 0.0 || trim_percent >= 0.5 {
abort("trim_percent must be in [0, 0.5)")
}
let sorted = []
for v in data {
sorted.push(v)
}
sorted.sort()
let n = sorted.length()
let k = (n.to_double() * trim_percent).to_int()
if k * 2 >= n {
return sorted
}
let lower_bound = sorted[k]
let upper_bound = sorted[n - 1 - k]
let result = []
for v in data {
if v < lower_bound {
result.push(lower_bound)
} else if v > upper_bound {
result.push(upper_bound)
} else {
result.push(v)
}
}
result
}
///|
pub fn winsorized_mean(data : Array[Double], trim_percent : Double) -> Double {
let w_data = winsorize(data, trim_percent)
if w_data.length() == 0 {
return 0.0
}
let mut sum = 0.0
for v in w_data {
sum += v
}
sum / w_data.length().to_double()
}