ggplot-rs 0.22.2

A Rust implementation of ggplot2's Grammar of Graphics
Documentation
pub mod dodge;
pub mod dodge2;
pub mod fill;
pub mod identity;
pub mod jitter;
pub mod jitterdodge;
pub mod nudge;
pub mod stack;

use crate::data::DataFrame;

/// Parameters for position adjustments.
#[derive(Clone, Debug)]
pub struct PositionParams {
    pub width: f64,
    pub height: f64,
}

impl Default for PositionParams {
    fn default() -> Self {
        PositionParams {
            width: 0.9,
            height: 0.0,
        }
    }
}

/// Trait for position adjustments.
pub trait Position: Send + Sync {
    /// Adjust positions for data.
    fn compute(&self, data: &mut DataFrame, params: &PositionParams);

    fn name(&self) -> &str;

    /// Whether this position must run separately per facet panel rather
    /// than once on the pooled rows before facets are split (B3-3, D8).
    /// Default `false`. `PositionStack`/`PositionFill` override this to
    /// `true` — a shared x category's stack height must not mix rows from
    /// different panels. Dodge and jitter stay pooled across panels for
    /// now (a follow-up, sipemu/ggplot-rs#154).
    fn per_panel(&self) -> bool {
        false
    }

    /// Validate this position's own parameters once per layer (D2);
    /// default no-op. Implementations push a warning and fall back to a
    /// sane default rather than panicking or silently miscomputing.
    fn validate(&self, _warnings: &mut Vec<String>) {}
}

/// Column in which stacking positions keep each row's original (pre-stack)
/// `y`, so hover metadata (`data-value`, tooltips) can report the measured
/// value rather than the cumulative stack top.
pub const RAW_Y_COL: &str = ".y_raw";

/// Remember the pre-position `y` in [`RAW_Y_COL`] (first adjustment wins).
pub(crate) fn preserve_raw_y(data: &mut DataFrame, y: &[crate::data::Value]) {
    if !data.has_column(RAW_Y_COL) {
        data.add_column(RAW_Y_COL.to_string(), y.to_vec());
    }
}

/// Column in which dodging positions store each row's offset (in category
/// units) when x is *discrete*: the category itself can't move, so geoms add
/// `offset / n_levels` to the mapped x (see `geom::support::XMapper`).
pub const DODGE_OFFSET_COL: &str = ".x_dodge_offset";
/// Number of dodged groups sharing a row's discrete x position (stored next to
/// [`DODGE_OFFSET_COL`]); bar-like geoms divide their width by it.
pub const DODGE_N_COL: &str = ".x_dodge_n";