//! Precomputed per-outcode and per-postcode-sector average crime rates. //! //! The right pane shows each crime metric's national average (the global //! feature-histogram mean). To let users see how an area compares with its //! immediate surroundings, we also precompute the mean headline crime rate //! (`"X (avg/yr)"`) across every property in the selection's outcode (e.g. //! `"E14"`) and postcode sector (e.g. `"E14 2"`). //! //! Crime figures are constant within a postcode (the pipeline merges them on //! the postcode key), so each postcode's value is read once — from its first //! row — and property-weighted by the postcode's row count. That keeps these //! averages on the same property-weighted basis as the national average, so the //! four numbers (this area / sector / outcode / nation) are directly comparable. use rustc_hash::FxHashMap; /// Crime-feature name suffix that marks an annualised headline-rate column /// (e.g. `"Burglary (avg/yr)"`). Stripped to derive the bare type name. pub const AVG_YR_SUFFIX: &str = " (avg/yr)"; pub struct AreaCrimeAverages { /// Bare crime-type names (suffix stripped, e.g. `"Burglary"`), index-aligned /// with the per-area mean vectors. Matches `CrimeYearStats.name`. pub crime_types: Vec, /// National mean headline rate per crime type (index-aligned with /// `crime_types`). An EXACT property-weighted mean over every postcode, so it /// shares a basis with `by_outcode`/`by_sector` and the per-selection mean — /// unlike the histogram-bin national average, which is biased upward for the /// right-skewed crime densities. `NaN` where no postcode has data. pub national: Vec, /// Outcode (e.g. `"E14"`) → mean headline rate per crime type. `NaN` where /// the outcode has no data for that type. pub by_outcode: FxHashMap>, /// Postcode sector (e.g. `"E14 2"`) → mean headline rate per crime type. pub by_sector: FxHashMap>, } impl AreaCrimeAverages { pub fn empty() -> Self { Self { crime_types: Vec::new(), national: Vec::new(), by_outcode: FxHashMap::default(), by_sector: FxHashMap::default(), } } }