This repository builds a reproducible operational risk index for Syrian subdistricts in October 2025. The index measures and ranks Syrian subdistricts by where return and arrival pressure overlaps with weak return conditions, humanitarian severity, recent emergency movement shocks, and settlement concentration.
The project was developed as a coding sample from a policy analysis exercise on Syrian returns, labour-market adjustment, and migration governance. It is designed to show a full empirical workflow with raw public data ingestion, cleaning, admin-code matching, geospatial processing, index construction, sensitivity checks, and map-ready output.
This is a descriptive screening index for policy and operational use cases related to return, reintegration, economic recovery, and labour-market adjustment. It flags subdistricts where return and arrival pressure is high and local conditions add stress. The aggregation is additive, so strong pressure can outweigh better return conditions. The CoRI-MMT quadrant figure below separates the two core dimensions to distinguish between high-pressure, weak-condition subdistricts from subdistricts driven by pressure alone.
Interactive Datawrapper map: https://www.datawrapper.de/_/vOdak/?v=2
Interactive Datawrapper chart: https://www.datawrapper.de/_/UhVCP/ (A code-generated version of the same figure (matplotlib) can be reproduced from the committed processed dataset: python scripts/11_make_cori_mmt_scatter.py)
Which Syrian subdistricts, in October 2025, combined high return and arrival pressure with weak local return conditions, broader humanitarian severity, emergency movement shocks, and settlement concentration?
The unit of analysis is Syrian admin3, or subdistrict.
The core time frame is October 2025. CoRI Round 3 and MMT Round 9 form the main data spine because they align in time and measure the two core concepts: return conditions and return or arrival pressure.
The pipeline uses the following public or humanitarian operational datasets:
| Source | Use in this repository |
|---|---|
| IOM DTM Communities of Return Index, Round 3 | Return-condition weakness by subdistrict |
| IOM DTM Population Mobility and Baseline Assessment, Round 9 | Return and arrival pressure by subdistrict |
| OCHA Syria JIAF 2025 | Inter-sector humanitarian severity |
| IOM DTM Emergency Mobility Tracking, Round 14 | Recent emergency movement shock where observed |
| GHSL WUP-DEGURBA 2025 | Population-weighted settlement concentration |
| ACAPS Syria Core Dataset | District-level validation checks only |
Raw files are not committed to this repository. The scripts expect them in data/raw/ using the folder structure described in docs/data_sources.md.
The index has two blocks.
First, the core return stress score combines CoRI return-condition weakness and MMT return or arrival pressure:
core_return_stress =
0.50 * CoRI weakness
+ 0.50 * MMT pressure
MMT pressure combines both absolute pressure and relative pressure:
MMT pressure =
0.50 * percentile rank of return/arrival count
+ 0.50 * percentile rank of return/arrival share
Second, the system stress modifier combines available system-stress signals:
system_stress_modifier =
mean(OCHA severity, GHSL settlement concentration, EMT shock where observed)
The final score is:
operational_risk_score =
0.70 * core_return_stress
+ 0.30 * system_stress_modifier
The score is calculated only for subdistricts with both CoRI Round 3 and MMT Round 9 data. EMT is used only where observed and is not imputed as zero outside covered areas.
The main processed dataset is data/processed/operational_risk_index_admin3_oct2025.csv.
The sensitivity-augmented processed dataset is data/processed/operational_risk_index_admin3_oct2025_with_sensitivity.csv.
The Datawrapper-ready map file is outputs/datawrapper/operational_risk_index_admin3_oct2025_map.csv.
The exported map image is outputs/figures/operational_risk_map_oct2025.png.
The repository tests whether the main score is stable under alternative assumptions:
- equal-weight available-component index
- CoRI/MMT-only index
- no-EMT index
- no-GHSL index
- no-OCHA index
- no-CoRI index
- no-MMT index
- 60/40 block-weight index
- top 20%, 25%, and 30% threshold checks
The sensitivity checks show that MMT pressure is the load-bearing component. This is expected because the index is designed to identify return-related local system stress, not general humanitarian severity. Dropping MMT lowers the rank correlation baseline to 0.36 so the main score should be read as a pressure-led index that the other components adjust at the margin.
Key sensitivity outputs are stored in:
outputs/tables/sensitivity_checks_summary.md
outputs/tables/sensitivity_rank_comparison.csv
outputs/tables/sensitivity_top20_overlap.csv
outputs/tables/sensitivity_threshold_summary.csv
A companion analysis, presented at the Harvard Center for Geographic Analysis GIS Institute, tested an earlier weighting variant of this index for spatial structure in ArcGIS. That variant shows statistically significant positive spatial autocorrelation (Global Moran's I = 0.28, z = 6.36), with Getis-Ord Gi* hot spots concentrated in the northwest and the central interior and cold spots on the coast. The spatial work uses a separate methodology and is not part of this pipeline. Running the same diagnostics on the final operational risk score is a planned second part of this project.
The repository aggregates the admin3 operational risk score to admin2 and compares it with selected ACAPS SABA October 2025 indicators. This is a face-validity check, not a causal test.
SABA indicators are not used in the main score because several SABA variables overlap with IOM and OCHA source data already used in the index.
Key validation outputs are stored in:
data/processed/saba_admin2_validation_oct2025.csv
outputs/tables/saba_validation_summary.md
outputs/tables/saba_validation_admin2_correlations.csv
Windows (PowerShell):
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements.txt
macOS / Linux:
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
Place raw source files in the required data/raw/ subfolders.
Then run:
python run_all.pyThe pipeline writes cleaned intermediate files to data/intermediate/, final scored outputs to data/processed/, Datawrapper-ready files to outputs/datawrapper/, and QA tables to outputs/tables/.
data/
raw/ # raw source files, not committed
intermediate/ # cleaned source-specific outputs
processed/ # final scored datasets
scripts/
00_inventory_sources.py
01_clean_cori_round3.py
02_clean_mmt_round9.py
03_clean_ocha_jiaf.py
04_clean_emt_round14.py
05a_inspect_ghsl_settlement_files.py
05_build_ghsl_settlement_concentration.py
06_merge_admin3_layers.py
07_construct_operational_risk_score.py
08_sensitivity_checks.py
09_saba_admin2_validation.py
10_make_datawrapper_map_csv.py
outputs/
tables/ # QA tables, sensitivity checks, and validation outputs
datawrapper/ # map-ready CSVs
figures/ # exported figures and map screenshots
docs/
method_note.md
data_sources.md
coding_sample_guide.md
This repository shows how I cleaned and linked public operational datasets, matched them across Syrian administrative codes, built a subdistrict-level screening index, documented missingness, tested sensitivity to alternative weights and components, and produced a Datawrapper-ready map. The index is descriptive and does not estimate labour-market effects, predict future movement, identify causal drivers of return, or measure household or employer behaviour.
Code in this repository is released under the MIT License.
Raw data are not redistributed unless source terms permit redistribution. Original data remain subject to the terms of their source institutions, including IOM DTM, OCHA, GHSL, and ACAPS.

