perfect-postcode/server-rs/src/data/area_crime_averages.rs
Andras Schmelczer fd2860070a
Some checks failed
Build and publish Docker image / build-and-push (push) Successful in 18m12s
CI / Check (push) Failing after 23m38s
lgtm
2026-06-22 22:12:27 +01:00

47 lines
2.2 KiB
Rust

//! 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<String>,
/// 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<f32>,
/// Outcode (e.g. `"E14"`) → mean headline rate per crime type. `NaN` where
/// the outcode has no data for that type.
pub by_outcode: FxHashMap<String, Vec<f32>>,
/// Postcode sector (e.g. `"E14 2"`) → mean headline rate per crime type.
pub by_sector: FxHashMap<String, Vec<f32>>,
}
impl AreaCrimeAverages {
pub fn empty() -> Self {
Self {
crime_types: Vec::new(),
national: Vec::new(),
by_outcode: FxHashMap::default(),
by_sector: FxHashMap::default(),
}
}
}