forked from vectordotdev/vector
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstatistic.rs
More file actions
90 lines (78 loc) · 2.17 KB
/
Copy pathstatistic.rs
File metadata and controls
90 lines (78 loc) · 2.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use snafu::Snafu;
use std::cmp::Ordering;
#[derive(Debug, Snafu)]
pub enum ValidationError {
#[snafu(display("Quantiles must be in range [0.0,1.0]"))]
QuantileOutOfRange,
}
pub struct DistributionStatistic {
pub min: f64,
pub max: f64,
pub median: f64,
pub avg: f64,
pub sum: f64,
pub count: u64,
/// (quantile, value)
pub quantiles: Vec<(f64, f64)>,
}
impl DistributionStatistic {
pub fn new(values: &[f64], counts: &[u32], quantiles: &[f64]) -> Option<Self> {
if values.len() != counts.len() {
return None;
}
let mut samples = Vec::new();
for (v, c) in values.iter().zip(counts.iter()) {
for _ in 0..*c {
samples.push(*v);
}
}
if samples.is_empty() {
return None;
}
if samples.len() == 1 {
let val = samples[0];
return Some(Self {
min: val,
max: val,
median: val,
avg: val,
sum: val,
count: 1,
quantiles: quantiles.iter().map(|&p| (p, val)).collect(),
});
}
samples.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal));
let length = samples.len() as f64;
let min = *samples.first().unwrap();
let max = *samples.last().unwrap();
let median = samples[(0.50 * length - 1.0).round() as usize];
let quantiles = quantiles
.iter()
.map(|&p| {
let sample = samples[(p * length - 1.0).round() as usize];
(p, sample)
})
.collect();
let sum = samples.iter().sum();
let avg = sum / length;
Some(Self {
min,
max,
median,
avg,
sum,
count: samples.len() as u64,
quantiles,
})
}
}
pub fn validate_quantiles(quantiles: &[f64]) -> Result<(), ValidationError> {
if quantiles
.iter()
.all(|&quantile| 0.0 <= quantile && quantile <= 1.0)
{
Ok(())
} else {
Err(ValidationError::QuantileOutOfRange)
}
}