Skip to content

Commit 762bd34

Browse files
Updates
1 parent f20d808 commit 762bd34

11 files changed

Lines changed: 1076 additions & 127 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,5 @@ interfaces/web/api/*.egg-info/
2626
*.swp
2727
*.swo
2828
.DS_Store
29+
30+
energy_shock_consumption.py

src/data/clean.rs

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,16 @@ fn write_households(dataset: &Dataset, output_dir: &Path) -> anyhow::Result<()>
194194
"benunit_ids", "person_ids",
195195
"weight", "region",
196196
"rent_annual", "council_tax_annual",
197+
// COICOP consumption
198+
"food_and_non_alcoholic_beverages", "alcohol_and_tobacco",
199+
"clothing_and_footwear", "housing_water_and_fuel",
200+
"household_furnishings", "health",
201+
"transport", "communication",
202+
"recreation_and_culture", "education",
203+
"restaurants_and_hotels", "miscellaneous_goods_and_services",
204+
"petrol_spending", "diesel_spending",
205+
// Product-level consumption (JSON blob)
206+
"consumption_products",
197207
])?;
198208

199209
for hh in &dataset.households {
@@ -206,6 +216,9 @@ fn write_households(dataset: &Dataset, output_dir: &Path) -> anyhow::Result<()>
206216
.collect::<Vec<_>>()
207217
.join(";");
208218

219+
// Serialize product-level consumption as JSON
220+
let products_json = serde_json::to_string(&hh.consumption_products).unwrap_or_else(|_| "{}".to_string());
221+
209222
wtr.write_record(&[
210223
hh.id.to_string(),
211224
bu_ids,
@@ -214,6 +227,21 @@ fn write_households(dataset: &Dataset, output_dir: &Path) -> anyhow::Result<()>
214227
hh.region.name().to_string(),
215228
format!("{:.2}", hh.rent),
216229
format!("{:.2}", hh.council_tax),
230+
format!("{:.2}", hh.food_and_non_alcoholic_beverages),
231+
format!("{:.2}", hh.alcohol_and_tobacco),
232+
format!("{:.2}", hh.clothing_and_footwear),
233+
format!("{:.2}", hh.housing_water_and_fuel),
234+
format!("{:.2}", hh.household_furnishings),
235+
format!("{:.2}", hh.health),
236+
format!("{:.2}", hh.transport),
237+
format!("{:.2}", hh.communication),
238+
format!("{:.2}", hh.recreation_and_culture),
239+
format!("{:.2}", hh.education),
240+
format!("{:.2}", hh.restaurants_and_hotels),
241+
format!("{:.2}", hh.miscellaneous_goods_and_services),
242+
format!("{:.2}", hh.petrol_spending),
243+
format!("{:.2}", hh.diesel_spending),
244+
products_json,
217245
])?;
218246
}
219247

@@ -603,11 +631,6 @@ pub fn load_clean_dataset(data_dir: &Path, year: u32) -> anyhow::Result<Dataset>
603631
})
604632
}
605633

606-
/// Backward-compatible alias.
607-
pub fn load_clean_frs(data_dir: &Path) -> anyhow::Result<Dataset> {
608-
load_clean_dataset(data_dir, 2023)
609-
}
610-
611634
/// Assemble a Dataset from pre-parsed entity vectors.
612635
pub fn assemble_dataset(
613636
mut people: Vec<Person>,
@@ -886,6 +909,14 @@ pub fn parse_households_csv<R: std::io::Read>(reader: R) -> anyhow::Result<Vec<H
886909

887910
for result in rdr.records() {
888911
let r = result?;
912+
// Parse product-level consumption from JSON blob (empty map if missing/malformed)
913+
let products_str = h.get_str(&r, "consumption_products");
914+
let consumption_products: HashMap<String, f64> = if products_str.is_empty() {
915+
HashMap::new()
916+
} else {
917+
serde_json::from_str(&products_str).unwrap_or_default()
918+
};
919+
889920
households.push(Household {
890921
id: h.get_usize(&r, "household_id"),
891922
benunit_ids: parse_id_list(&h.get_str(&r, "benunit_ids")),
@@ -894,6 +925,22 @@ pub fn parse_households_csv<R: std::io::Read>(reader: R) -> anyhow::Result<Vec<H
894925
region: parse_region(&h.get_str(&r, "region")),
895926
rent: h.get_f64(&r, "rent_annual"),
896927
council_tax: h.get_f64(&r, "council_tax_annual"),
928+
// COICOP consumption (present in LCFS clean CSVs, zero for others)
929+
food_and_non_alcoholic_beverages: h.get_f64(&r, "food_and_non_alcoholic_beverages"),
930+
alcohol_and_tobacco: h.get_f64(&r, "alcohol_and_tobacco"),
931+
clothing_and_footwear: h.get_f64(&r, "clothing_and_footwear"),
932+
housing_water_and_fuel: h.get_f64(&r, "housing_water_and_fuel"),
933+
household_furnishings: h.get_f64(&r, "household_furnishings"),
934+
health: h.get_f64(&r, "health"),
935+
transport: h.get_f64(&r, "transport"),
936+
communication: h.get_f64(&r, "communication"),
937+
recreation_and_culture: h.get_f64(&r, "recreation_and_culture"),
938+
education: h.get_f64(&r, "education"),
939+
restaurants_and_hotels: h.get_f64(&r, "restaurants_and_hotels"),
940+
miscellaneous_goods_and_services: h.get_f64(&r, "miscellaneous_goods_and_services"),
941+
petrol_spending: h.get_f64(&r, "petrol_spending"),
942+
diesel_spending: h.get_f64(&r, "diesel_spending"),
943+
consumption_products,
897944
});
898945
}
899946

src/data/frs.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ pub fn load_frs(data_dir: &Path, fiscal_year: u32) -> anyhow::Result<Dataset> {
9999

100100
// ── Table loading ────────────────────────────────────────────────────────
101101

102-
type Table = Vec<HashMap<String, String>>;
102+
pub(crate) type Table = Vec<HashMap<String, String>>;
103103

104-
fn load_table_cols(data_dir: &Path, name: &str, needed: Option<&[&str]>) -> anyhow::Result<Table> {
104+
pub(crate) fn load_table_cols(data_dir: &Path, name: &str, needed: Option<&[&str]>) -> anyhow::Result<Table> {
105105
let tab_path = data_dir.join(format!("{}.tab", name));
106106
let csv_path = data_dir.join(format!("{}.csv", name));
107107

@@ -140,19 +140,19 @@ fn load_table_cols(data_dir: &Path, name: &str, needed: Option<&[&str]>) -> anyh
140140
Ok(table)
141141
}
142142

143-
fn get_f64(row: &HashMap<String, String>, key: &str) -> f64 {
143+
pub(crate) fn get_f64(row: &HashMap<String, String>, key: &str) -> f64 {
144144
row.get(key)
145145
.and_then(|s| s.trim().parse::<f64>().ok())
146146
.unwrap_or(0.0)
147147
}
148148

149-
fn get_i64(row: &HashMap<String, String>, key: &str) -> i64 {
149+
pub(crate) fn get_i64(row: &HashMap<String, String>, key: &str) -> i64 {
150150
row.get(key)
151151
.and_then(|s| s.trim().parse::<i64>().ok())
152152
.unwrap_or(0)
153153
}
154154

155-
fn get_positive_f64(row: &HashMap<String, String>, key: &str) -> f64 {
155+
pub(crate) fn get_positive_f64(row: &HashMap<String, String>, key: &str) -> f64 {
156156
get_f64(row, key).max(0.0)
157157
}
158158

@@ -227,7 +227,7 @@ struct HouseholdRecord {
227227
cvpay_weekly: f64,
228228
}
229229

230-
fn region_from_gvtregno(code: i64) -> Region {
230+
pub(crate) fn region_from_gvtregno(code: i64) -> Region {
231231
match code {
232232
1 => Region::NorthEast,
233233
2 => Region::NorthWest,
@@ -917,6 +917,7 @@ fn assemble_dataset(
917917
region: hh.region,
918918
rent: hh.rent_weekly * WEEKS_IN_YEAR,
919919
council_tax: hh.council_tax_annual,
920+
..Household::default()
920921
});
921922
}
922923

0 commit comments

Comments
 (0)