Initial commit to repo.
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quartile_calculator"
|
||||||
|
version = "0.1.0"
|
||||||
6
Cargo.toml
Normal file
6
Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "quartile_calculator"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
40
main.py
Normal file
40
main.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
from sys import float_info
|
||||||
|
from typing import TypeAlias;
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DatasetCalculator:
|
||||||
|
data_set: list[float]
|
||||||
|
|
||||||
|
def first_quartile(self) -> float:
|
||||||
|
self.lower_data_set()
|
||||||
|
|
||||||
|
def second_quartile(self) -> float:
|
||||||
|
...
|
||||||
|
|
||||||
|
def third_quartile(self) -> float:
|
||||||
|
...
|
||||||
|
|
||||||
|
def interquartile_range(self) -> float:
|
||||||
|
...
|
||||||
|
|
||||||
|
def semi_interquartile_range(self) -> float:
|
||||||
|
...
|
||||||
|
|
||||||
|
def strip_outliers(self) -> DatasetCalculator:
|
||||||
|
...
|
||||||
|
|
||||||
|
def lower_data_set(self) -> DatasetCalculator:
|
||||||
|
...
|
||||||
|
|
||||||
|
def upper_data_set(self) -> DatasetCalculator:
|
||||||
|
...
|
||||||
|
|
||||||
|
def median(self) -> float:
|
||||||
|
...
|
||||||
|
|
||||||
|
def main():
|
||||||
|
...
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
241
src/main.rs
Normal file
241
src/main.rs
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
fn main() {
|
||||||
|
let arizona_state: Vec<f64> = vec![11.0, 16.0, 16.0, 16.0, 9.0, 15.0];
|
||||||
|
|
||||||
|
let colorado: Vec<f64> = vec![10.0, 15.0, 12.0, 12.0, 20.0];
|
||||||
|
|
||||||
|
let iowa: Vec<f64> = vec![18.0, 10.0, 13.0, 17.0, 19.0, 16.0, 18.0];
|
||||||
|
|
||||||
|
let nebraska: Vec<f64> = vec![15.0, 28.0, 15.0, 20.0, 10.0, 11.0, 12.0];
|
||||||
|
|
||||||
|
let south_carolina: Vec<f64> = vec![18.0, 15.0, 10.0, 18.0];
|
||||||
|
|
||||||
|
let syracuse: Vec<f64> = vec![14.0, 19.0, 11.0, 15.0, 19.0];
|
||||||
|
|
||||||
|
let texas: Vec<f64> = vec![20.0, 17.0, 9.0, 9.0, 27.0];
|
||||||
|
|
||||||
|
println!("Arizona Average: {}", average(&arizona_state));
|
||||||
|
println!("Colorado Average: {}", average(&colorado));
|
||||||
|
println!("Iowa Average: {}", average(&iowa));
|
||||||
|
println!("Nebraska Average: {}", average(&nebraska));
|
||||||
|
println!("SouthCarolina Average: {}", average(&south_carolina));
|
||||||
|
println!("Syracuse Average: {}", average(&syracuse));
|
||||||
|
println!("TexasAnM Average: {}", average(&texas));
|
||||||
|
|
||||||
|
let mut set: Vec<f64> = vec![];
|
||||||
|
set.extend(arizona_state);
|
||||||
|
set.extend(colorado);
|
||||||
|
set.extend(iowa);
|
||||||
|
set.extend(nebraska);
|
||||||
|
set.extend(south_carolina);
|
||||||
|
set.extend(syracuse);
|
||||||
|
set.extend(texas);
|
||||||
|
|
||||||
|
let mut d = Dataset::from(set);
|
||||||
|
println!("Pre-outlier Stripping: {:#?}", d.0);
|
||||||
|
|
||||||
|
println!("Q1: {}", d.quartile(Quartile::First));
|
||||||
|
println!("Q2: {}", d.quartile(Quartile::Second));
|
||||||
|
println!("Q3: {}", d.quartile(Quartile::Third));
|
||||||
|
|
||||||
|
d.strip_outliers();
|
||||||
|
println!("Outliers Stripped: {:#?}", d.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn average(values: &Vec<f64>) -> f64 {
|
||||||
|
values.iter().sum::<f64>() / values.len() as f64
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
struct Dataset(Vec<f64>);
|
||||||
|
|
||||||
|
impl From<Vec<f64>> for Dataset {
|
||||||
|
fn from(mut value: Vec<f64>) -> Self {
|
||||||
|
Dataset({
|
||||||
|
value.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
||||||
|
value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dataset {
|
||||||
|
fn quartile(&self, quartile: Quartile) -> f64 {
|
||||||
|
let data_set = match quartile {
|
||||||
|
Quartile::First => self.half_data_set(Half::Lower),
|
||||||
|
Quartile::Second => self.clone(),
|
||||||
|
Quartile::Third => self.half_data_set(Half::Upper),
|
||||||
|
};
|
||||||
|
|
||||||
|
data_set.median()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a half of the data set.
|
||||||
|
/// This method may get screwy with very small datasets.
|
||||||
|
fn half_data_set(&self, half: Half) -> Self {
|
||||||
|
let mut data = self.0.clone();
|
||||||
|
let length = data.len();
|
||||||
|
let middle_idx = length / 2;
|
||||||
|
|
||||||
|
if (length % 2) != 0 {
|
||||||
|
data.remove(middle_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
let data_set = match half {
|
||||||
|
Half::Lower => Dataset({
|
||||||
|
let _ = data.split_off(middle_idx);
|
||||||
|
data
|
||||||
|
}),
|
||||||
|
Half::Upper => Dataset(data.split_off(middle_idx)),
|
||||||
|
};
|
||||||
|
|
||||||
|
data_set
|
||||||
|
}
|
||||||
|
|
||||||
|
fn median(&self) -> f64 {
|
||||||
|
let data = self.0.clone();
|
||||||
|
let length = data.len();
|
||||||
|
|
||||||
|
let a = data[length / 2];
|
||||||
|
|
||||||
|
let median = if (length % 2) == 0 {
|
||||||
|
let s: [f64; 2] = [a, data[(length / 2) - 1]];
|
||||||
|
|
||||||
|
s.iter().sum::<f64>() / 2_f64
|
||||||
|
} else {
|
||||||
|
a
|
||||||
|
};
|
||||||
|
|
||||||
|
median
|
||||||
|
}
|
||||||
|
|
||||||
|
fn interquartile_range(&self) -> f64 {
|
||||||
|
self.quartile(Quartile::Third) - self.quartile(Quartile::First)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn strip_outliers(&mut self) {
|
||||||
|
let mut data: Vec<f64>;
|
||||||
|
|
||||||
|
let first_quartile = self.quartile(Quartile::First);
|
||||||
|
let third_quartile = self.quartile(Quartile::Third);
|
||||||
|
let iqr_margin = 1.5 * self.interquartile_range();
|
||||||
|
|
||||||
|
// Filter low outliers
|
||||||
|
data = self
|
||||||
|
.0
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|x| {
|
||||||
|
if x >= (first_quartile - iqr_margin) {
|
||||||
|
Some(x)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<f64>>();
|
||||||
|
|
||||||
|
// Filter high outliers.
|
||||||
|
data = data
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|x| {
|
||||||
|
if x <= (third_quartile + iqr_margin) {
|
||||||
|
Some(x)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<f64>>();
|
||||||
|
|
||||||
|
self.0 = data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Percentile(Vec<f64>);
|
||||||
|
|
||||||
|
enum Quartile {
|
||||||
|
First,
|
||||||
|
Second,
|
||||||
|
Third,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Half {
|
||||||
|
Upper,
|
||||||
|
Lower,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn odd_quartiles() {
|
||||||
|
let d = Dataset::from(vec![
|
||||||
|
1_f64, 2_f64, 3_f64, 4_f64, 5_f64, 6_f64, 7_f64, 8_f64, 9_f64, 10_f64, 11_f64,
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert_eq!(d.quartile(Quartile::First), 3_f64);
|
||||||
|
assert_eq!(d.quartile(Quartile::Second), 6_f64);
|
||||||
|
assert_eq!(d.quartile(Quartile::Third), 9_f64);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn even_quartiles() {
|
||||||
|
let d = Dataset::from(vec![
|
||||||
|
1_f64, 2_f64, 3_f64, 4_f64, 5_f64, 6_f64, 7_f64, 8_f64, 9_f64, 10_f64, 11_f64, 12_f64,
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert_eq!(d.quartile(Quartile::First), 3.5_f64);
|
||||||
|
assert_eq!(d.quartile(Quartile::Second), 6.5_f64);
|
||||||
|
assert_eq!(d.quartile(Quartile::Third), 9.5_f64);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn odd_dataset_halves() {
|
||||||
|
let d = Dataset::from(vec![
|
||||||
|
1_f64, 2_f64, 3_f64, 4_f64, 5_f64, 6_f64, 7_f64, 8_f64, 9_f64, 10_f64, 11_f64,
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
d.half_data_set(Half::Lower),
|
||||||
|
Dataset::from(vec![1_f64, 2_f64, 3_f64, 4_f64, 5_f64])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
d.half_data_set(Half::Upper),
|
||||||
|
Dataset::from(vec![7_f64, 8_f64, 9_f64, 10_f64, 11_f64])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn even_dataset_halves() {
|
||||||
|
let d = Dataset::from(vec![
|
||||||
|
1_f64, 2_f64, 3_f64, 4_f64, 5_f64, 6_f64, 7_f64, 8_f64, 9_f64, 10_f64, 11_f64, 12_f64,
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
d.half_data_set(Half::Lower),
|
||||||
|
Dataset::from(vec![1_f64, 2_f64, 3_f64, 4_f64, 5_f64, 6_f64])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
d.half_data_set(Half::Upper),
|
||||||
|
Dataset::from(vec![7_f64, 8_f64, 9_f64, 10_f64, 11_f64, 12_f64])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn interquartile_range() {
|
||||||
|
let d = Dataset::from(vec![
|
||||||
|
1_f64, 2_f64, 3_f64, 4_f64, 5_f64, 6_f64, 7_f64, 8_f64, 9_f64, 10_f64, 11_f64, 12_f64,
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert_eq!(d.interquartile_range(), 6_f64)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn strip_outliers() {
|
||||||
|
let mut d = Dataset::from(vec![
|
||||||
|
1_f64, 7_f64, 8_f64, 9_f64, 10_f64, 11_f64, 12_f64, 98_f64,
|
||||||
|
]);
|
||||||
|
|
||||||
|
d.strip_outliers();
|
||||||
|
|
||||||
|
assert_eq!(d.0, vec![7_f64, 8_f64, 9_f64, 10_f64, 11_f64, 12_f64])
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user