plotlars 0.12.0

Plotlars is a Rust library designed to facilitate the integration between the Polars data analysis library and visualization libraries.
use plotlars::polars::prelude::*;
use plotlars::{
    Axis, BarPlot, BoxPlot, CsvReader, Dimensions, Legend, Line, Orientation, Rgb, ScatterPlot,
    Shape, SubplotGrid, Text, TickDirection, TimeSeriesPlot,
};

fn main() {
    let penguins_dataset = CsvReader::new("data/penguins.csv")
        .finish()
        .unwrap()
        .lazy()
        .select([
            col("species"),
            col("sex").alias("gender"),
            col("flipper_length_mm").cast(DataType::Int16),
            col("body_mass_g").cast(DataType::Int16),
        ])
        .collect()
        .unwrap();

    let temperature_dataset = CsvReader::new("data/debilt_2023_temps.csv")
        .has_header(true)
        .try_parse_dates(true)
        .finish()
        .unwrap()
        .lazy()
        .with_columns(vec![
            (col("tavg") / lit(10)).alias("tavg"),
            (col("tmin") / lit(10)).alias("tmin"),
            (col("tmax") / lit(10)).alias("tmax"),
        ])
        .collect()
        .unwrap();

    let animals_dataset = CsvReader::new("data/animal_statistics.csv")
        .finish()
        .unwrap();

    let axis = Axis::new()
        .show_line(true)
        .tick_direction(TickDirection::OutSide)
        .value_thousands(true);

    let plot1 = TimeSeriesPlot::builder()
        .data(&temperature_dataset)
        .x("date")
        .y("tavg")
        .additional_series(vec!["tmin", "tmax"])
        .colors(vec![Rgb(128, 128, 128), Rgb(0, 122, 255), Rgb(255, 128, 0)])
        .lines(vec![Line::Solid, Line::Dot, Line::Dot])
        .plot_title(
            Text::from("De Bilt Temperature 2023")
                .font("Arial Black")
                .size(16),
        )
        .y_title(Text::from("temperature (°C)").size(13).x(-0.08))
        // .legend_title(Text::from("Measure").size(12))
        .legend(&Legend::new().x(0.1).y(0.9))
        .build();

    let plot2 = ScatterPlot::builder()
        .data(&penguins_dataset)
        .x("body_mass_g")
        .y("flipper_length_mm")
        .group("species")
        .sort_groups_by(|a, b| {
            if a.len() == b.len() {
                a.cmp(b)
            } else {
                a.len().cmp(&b.len())
            }
        })
        .opacity(0.6)
        .size(10)
        .colors(vec![Rgb(178, 34, 34), Rgb(65, 105, 225), Rgb(255, 140, 0)])
        .shapes(vec![Shape::Circle, Shape::Square, Shape::Diamond])
        .plot_title(
            Text::from("Penguin Morphology")
                .font("Arial Black")
                .size(16),
        )
        .x_title(Text::from("body mass (g)").size(13))
        .y_title(Text::from("flipper length (mm)").size(13).x(-0.11))
        .legend_title(Text::from("Species").size(12))
        .x_axis(&axis.clone().value_range(2500.0, 6500.0))
        .y_axis(&axis.clone().value_range(170.0, 240.0))
        .legend(&Legend::new().x(0.85).y(0.4))
        .build();

    let plot3 = BarPlot::builder()
        .data(&animals_dataset)
        .labels("animal")
        .values("value")
        .orientation(Orientation::Vertical)
        .group("gender")
        .sort_groups_by(|a, b| a.len().cmp(&b.len()))
        .error("error")
        .colors(vec![Rgb(255, 127, 80), Rgb(64, 224, 208)])
        .plot_title(Text::from("Animal Statistics").font("Arial Black").size(16))
        .x_title(Text::from("animal").size(13))
        .y_title(Text::from("value").size(13))
        .legend_title(Text::from("Gender").size(12))
        .legend(
            &Legend::new()
                .orientation(Orientation::Horizontal)
                .x(0.35)
                .y(0.9),
        )
        .build();

    let plot4 = BoxPlot::builder()
        .data(&penguins_dataset)
        .labels("species")
        .values("body_mass_g")
        .orientation(Orientation::Vertical)
        .group("gender")
        .box_points(true)
        .point_offset(-1.5)
        .jitter(0.01)
        .opacity(0.15)
        .colors(vec![Rgb(0, 191, 255), Rgb(57, 255, 20), Rgb(255, 105, 180)])
        .plot_title(
            Text::from("Body Mass Distribution")
                .font("Arial Black")
                .size(16),
        )
        .x_title(Text::from("species").size(13))
        .y_title(Text::from("body mass (g)").size(13).x(-0.12))
        .legend_title(Text::from("Gender").size(12))
        .y_axis(&Axis::new().value_thousands(true))
        .legend(&Legend::new().x(0.85).y(0.9))
        .build();

    let dimensions = Dimensions::new().width(1400).height(850).auto_size(false);

    SubplotGrid::regular()
        .plots(vec![&plot1, &plot2, &plot3, &plot4])
        .rows(2)
        .cols(2)
        .v_gap(0.3)
        .h_gap(0.2)
        .dimensions(&dimensions)
        .title(
            Text::from("Scientific Data Visualization Dashboard")
                .size(26)
                .font("Arial Black"),
        )
        .build()
        .plot();
}