use crate::error::StatError;
use crate::nan::{clean, NanPolicy};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Ties {
Average,
Min,
Max,
Dense,
Ordinal,
}
pub fn rank(v: &[f64], ties: Ties) -> Result<Vec<f64>, StatError> {
let data = clean(v, NanPolicy::Omit)?;
let n = data.len();
let mut idx: Vec<usize> = (0..n).collect();
idx.sort_by(|&a, &b| data[a].partial_cmp(&data[b]).unwrap());
let mut out = vec![0.0f64; n];
let mut i = 0usize;
let mut group_counter = 0usize; while i < n {
let mut j = i + 1;
while j < n && data[idx[j]] == data[idx[i]] {
j += 1;
}
group_counter += 1;
let lo = i + 1; let hi = j;
match ties {
Ties::Average => {
let avg = (lo + hi) as f64 / 2.0;
for k in i..j {
out[idx[k]] = avg;
}
}
Ties::Min => {
for k in i..j {
out[idx[k]] = lo as f64;
}
}
Ties::Max => {
for k in i..j {
out[idx[k]] = hi as f64;
}
}
Ties::Dense => {
for k in i..j {
out[idx[k]] = group_counter as f64;
}
}
Ties::Ordinal => {
for (rank_offset, k) in (i..j).enumerate() {
out[idx[k]] = (lo + rank_offset) as f64;
}
}
}
i = j;
}
Ok(out)
}