Skip to main content

Histogram

Struct Histogram 

Source
pub struct Histogram {
    pub edges: Vec<f64>,
    pub counts: Vec<usize>,
}
Expand description

An equal-width histogram over the non-missing values of a numeric column.

The bin count follows Sturges’ rule (ceil(log2(n) + 1), floored at 1). edges.len() == counts.len() + 1; the final bin is inclusive of its upper edge so the maximum value is never dropped.

Fields§

§edges: Vec<f64>

Bin edges, ascending. Length is counts.len() + 1 (empty for an empty column).

§counts: Vec<usize>

Number of values falling into each bin. Length is one less than edges.

Implementations§

Source§

impl Histogram

Source

pub fn nbins(&self) -> usize

Returns the number of bins (== counts.len()).

Examples found in repository?
examples/numeric_distribution.rs (line 63)
11fn main() -> datarust_profile::Result<()> {
12    // A synthetic column with a visible right skew: most values cluster low,
13    // one extreme value pulls the tail.
14    let m = Matrix::from_rows(vec![
15        vec![10.0],
16        vec![12.0],
17        vec![11.0],
18        vec![13.0],
19        vec![10.0],
20        vec![14.0],
21        vec![12.0],
22        vec![11.0],
23        vec![150.0], // outlier — well above the IQR fence
24    ])?;
25
26    let p = profile_matrix(&m, Some(&["reaction_ms".into()]))?;
27    let col = &p.columns[0];
28    let n = col.numeric.as_ref().expect("numeric column");
29
30    println!(
31        "Column: {} ({} rows, {} missing)\n",
32        col.name, col.count, col.missing_count
33    );
34
35    // Central tendency + spread.
36    println!("  mean   = {:.2}", n.mean);
37    println!("  std    = {:.2}\n", n.std);
38
39    // Five-number summary (min / Q1 / median / Q3 / max).
40    println!("  five-number summary:");
41    println!("    min    = {:.1}", n.five.min);
42    println!("    Q1     = {:.1}", n.five.q1);
43    println!("    median = {:.1}", n.five.median);
44    println!("    Q3     = {:.1}", n.five.q3);
45    println!("    max    = {:.1}\n", n.five.max);
46
47    // Distributional shape (v0.2).
48    //   skew ≈ 0  → symmetric; large positive → right tail (our case).
49    //   excess kurtosis ≈ 0 → normal-like; positive → heavy-tailed.
50    println!("  shape:");
51    println!(
52        "    skewness  = {:+.3}  ({})",
53        n.skewness,
54        describe_skew(n.skewness)
55    );
56    println!(
57        "    kurtosis  = {:+.3}  ({})\n",
58        n.kurtosis,
59        describe_kurtosis(n.kurtosis)
60    );
61
62    // Histogram — equal-width bins, Sturges' rule for the count.
63    println!("  histogram ({} bins):", n.histogram.nbins());
64    let max_count = n.histogram.max_count().max(1);
65    for (i, &count) in n.histogram.counts.iter().enumerate() {
66        let lo = n.histogram.edges.get(i).copied().unwrap_or(f64::NAN);
67        let hi = n.histogram.edges.get(i + 1).copied().unwrap_or(f64::NAN);
68        let bar_len = (count as f64 / max_count as f64 * 40.0).round() as usize;
69        let bar: String = "█".repeat(bar_len);
70        println!("    [{:>7.1}, {:>7.1})  {:>3}  {}", lo, hi, count, bar);
71    }
72    println!();
73
74    // Outliers — values beyond the Tukey IQR fences.
75    println!("  outliers (IQR rule):");
76    println!(
77        "    {} found ({:.1}% of values)\n",
78        n.outlier_count,
79        n.outlier_fraction * 100.0
80    );
81
82    Ok(())
83}
Source

pub fn max_count(&self) -> usize

Returns the count in the tallest bin, or 0 for an empty histogram.

Examples found in repository?
examples/numeric_distribution.rs (line 64)
11fn main() -> datarust_profile::Result<()> {
12    // A synthetic column with a visible right skew: most values cluster low,
13    // one extreme value pulls the tail.
14    let m = Matrix::from_rows(vec![
15        vec![10.0],
16        vec![12.0],
17        vec![11.0],
18        vec![13.0],
19        vec![10.0],
20        vec![14.0],
21        vec![12.0],
22        vec![11.0],
23        vec![150.0], // outlier — well above the IQR fence
24    ])?;
25
26    let p = profile_matrix(&m, Some(&["reaction_ms".into()]))?;
27    let col = &p.columns[0];
28    let n = col.numeric.as_ref().expect("numeric column");
29
30    println!(
31        "Column: {} ({} rows, {} missing)\n",
32        col.name, col.count, col.missing_count
33    );
34
35    // Central tendency + spread.
36    println!("  mean   = {:.2}", n.mean);
37    println!("  std    = {:.2}\n", n.std);
38
39    // Five-number summary (min / Q1 / median / Q3 / max).
40    println!("  five-number summary:");
41    println!("    min    = {:.1}", n.five.min);
42    println!("    Q1     = {:.1}", n.five.q1);
43    println!("    median = {:.1}", n.five.median);
44    println!("    Q3     = {:.1}", n.five.q3);
45    println!("    max    = {:.1}\n", n.five.max);
46
47    // Distributional shape (v0.2).
48    //   skew ≈ 0  → symmetric; large positive → right tail (our case).
49    //   excess kurtosis ≈ 0 → normal-like; positive → heavy-tailed.
50    println!("  shape:");
51    println!(
52        "    skewness  = {:+.3}  ({})",
53        n.skewness,
54        describe_skew(n.skewness)
55    );
56    println!(
57        "    kurtosis  = {:+.3}  ({})\n",
58        n.kurtosis,
59        describe_kurtosis(n.kurtosis)
60    );
61
62    // Histogram — equal-width bins, Sturges' rule for the count.
63    println!("  histogram ({} bins):", n.histogram.nbins());
64    let max_count = n.histogram.max_count().max(1);
65    for (i, &count) in n.histogram.counts.iter().enumerate() {
66        let lo = n.histogram.edges.get(i).copied().unwrap_or(f64::NAN);
67        let hi = n.histogram.edges.get(i + 1).copied().unwrap_or(f64::NAN);
68        let bar_len = (count as f64 / max_count as f64 * 40.0).round() as usize;
69        let bar: String = "█".repeat(bar_len);
70        println!("    [{:>7.1}, {:>7.1})  {:>3}  {}", lo, hi, count, bar);
71    }
72    println!();
73
74    // Outliers — values beyond the Tukey IQR fences.
75    println!("  outliers (IQR rule):");
76    println!(
77        "    {} found ({:.1}% of values)\n",
78        n.outlier_count,
79        n.outlier_fraction * 100.0
80    );
81
82    Ok(())
83}

Trait Implementations§

Source§

impl Clone for Histogram

Source§

fn clone(&self) -> Histogram

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Histogram

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for Histogram

Source§

fn eq(&self, other: &Histogram) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Histogram

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.