rust_shap 0.1.0

A lightweight Rust implementation of Kernel SHAP
Documentation
// ========================================================================================
//  explanation.rs   — Rust translation of shap/explanation.py
// ========================================================================================

use serde::{Serialize, Deserialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Explanation {
    pub shap_values: Vec<Vec<f64>>,
    pub base_value: f64,
    pub feature_names: Option<Vec<String>>,
    pub data: Option<Vec<f64>>,
    pub metadata: Option<std::collections::HashMap<String, String>>,
}
impl Explanation {
    pub fn new(
        shap_values: Vec<Vec<f64>>,
        base_value: f64,
        feature_names: Option<Vec<String>>,
        data: Option<Vec<f64>>,
        metadata: Option<std::collections::HashMap<String, String>>,
    ) -> Self {
        Self {
            shap_values,
            base_value,
            feature_names,
            data,
            metadata,
        }
    }
    pub fn values(&self) -> &Vec<Vec<f64>> {
        &self.shap_values
    }
    pub fn summary(&self) {
        println!("SHAP Explanation Summary");
        println!("------------------------");
        println!("Base value: {}", self.base_value);

        match &self.feature_names {
            Some(names) => println!("Features: {:?}", names),
            None => println!("Features: None"),
        }

        println!(
            "SHAP matrix: {} samples × {} features",
            self.shap_values.len(),
            if self.shap_values.is_empty() { 0 } else { self.shap_values[0].len() }
        );

        if let Some(d) = &self.data {
            println!("Contains data sample of length {}", d.len());
        } else {
            println!("Data sample: None");
        }
    }
}
impl Explanation {
    // Example helper: get shap values for a single feature index
    pub fn shap_for_feature(&self, index: usize) -> Option<Vec<f64>> {
        if self.shap_values.is_empty() || index >= self.shap_values[0].len() {
            return None;
        }

        // Extract column of shap values
        let mut column = Vec::new();
        for row in &self.shap_values {
            column.push(row[index]);
        }
        Some(column)
    }
}