plotters-statistical 0.1.0

Statistical chart primitives (box, violin, ROC, PR, regularization-path, residual) as native plotters series
Documentation
//! Two overlaid empirical CDFs (one with a 95% DKW confidence band), rendered to
//! `ecdf.svg`.

use plotters::prelude::*;
use plotters_statistical::style::palette_color;
use plotters_statistical::Ecdf;

fn sample(shift: f64, n: usize) -> Vec<f64> {
    (0..n)
        .map(|i| {
            let t = (i as f64 + 0.5) / n as f64;
            // Inverse-logistic-ish spread, shifted per group.
            shift + (t / (1.0 - t)).ln()
        })
        .collect()
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let root = SVGBackend::new("ecdf.svg", (720, 480)).into_drawing_area();
    root.fill(&WHITE)?;

    let mut chart = ChartBuilder::on(&root)
        .caption("Empirical CDF", ("sans-serif", 24))
        .margin(20)
        .set_label_area_size(LabelAreaPosition::Left, 45)
        .set_label_area_size(LabelAreaPosition::Bottom, 40)
        .build_cartesian_2d(-6f64..6f64, 0f64..1f64)?;
    chart
        .configure_mesh()
        .x_desc("value")
        .y_desc("F(x)")
        .draw()?;

    let a = sample(-1.5, 120);
    let b = sample(1.5, 120);

    chart
        .draw_series(std::iter::once(
            Ecdf::from_data(&a)?
                .color(palette_color(0))
                .confidence_band(0.05),
        ))?
        .label("group A (95% band)")
        .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 18, y)], palette_color(0)));
    chart
        .draw_series(std::iter::once(
            Ecdf::from_data(&b)?.color(palette_color(1)),
        ))?
        .label("group B")
        .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 18, y)], palette_color(1)));

    chart
        .configure_series_labels()
        .position(SeriesLabelPosition::UpperLeft)
        .border_style(BLACK)
        .background_style(WHITE.mix(0.85))
        .draw()?;
    root.present()?;
    println!("wrote ecdf.svg");
    Ok(())
}