plotters-statistical 0.1.0

Statistical chart primitives (box, violin, ROC, PR, regularization-path, residual) as native plotters series
Documentation
//! Multi-group violin plot rendered to `violin_plot.svg`, shown both without and
//! with the embedded box-plot overlay (left / right panels).

use plotters::prelude::*;
use plotters_statistical::ViolinPlotSeries;

fn sample(center: f64, spread: f64, n: usize) -> Vec<f64> {
    // Deterministic pseudo-sample: a couple of sinusoidal "modes" around center.
    (0..n)
        .map(|i| {
            let t = i as f64 / n as f64;
            center + spread * ((t * std::f64::consts::TAU * 2.0).sin() + (t - 0.5) * 2.0)
        })
        .collect()
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let root = SVGBackend::new("violin_plot.svg", (960, 500)).into_drawing_area();
    root.fill(&WHITE)?;
    let (left, right) = root.split_horizontally(480);

    let groups = || {
        vec![
            (1.0f64, sample(6.0, 1.5, 120)),
            (2.0f64, sample(3.5, 1.0, 120)),
            (3.0f64, sample(8.0, 2.0, 120)),
        ]
    };

    for (area, title, with_box) in [
        (&left, "Violins", false),
        (&right, "Violins + embedded box", true),
    ] {
        let mut chart = ChartBuilder::on(area)
            .caption(title, ("sans-serif", 22))
            .margin(20)
            .set_label_area_size(LabelAreaPosition::Left, 45)
            .set_label_area_size(LabelAreaPosition::Bottom, 40)
            .build_cartesian_2d(0.5f64..3.5f64, 0f64..14f64)?;
        chart
            .configure_mesh()
            .x_desc("group")
            .y_desc("value")
            .draw()?;
        chart.draw_series(
            ViolinPlotSeries::from_samples(groups())?
                .width(90)
                .show_box(with_box),
        )?;
    }

    root.present()?;
    println!("wrote violin_plot.svg");
    Ok(())
}