# AMOD 5430 Final Project Code

This folder contains the code and sample data used for the exploratory analysis,
maps, and classification experiments in the paper **Spatiotemporal Analysis and
Predictive Modeling of Community Safety Indicators in Toronto**.

## Contents

- `src/analysis.py`: command-line script for the full analysis.
- `data/sample_csi_data.csv`: a 5,000-row stratified sample for testing the code.
- `output/`: figures and results produced from the full dataset.
- `requirements.txt`: Python dependencies.

The original CSV is 156 MB and is not included in the ZIP. The sample keeps only
the columns used by the script, so it is enough to run the analysis from start to
finish.

## Requirements

- Python 3.11 or newer
- Approximately 2 GB of free memory for the full data

Create an isolated environment from this directory:

```bash
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
```

On Windows PowerShell, activate with `.venv\Scripts\Activate.ps1`.

## Run with the included sample

```bash
python src/analysis.py \
  --input data/sample_csi_data.csv \
  --output output_sample
```

This command creates all four figure groups and fits both classifiers. It also
writes the model results as JSON and CSV files. With only 5,000 rows, the sample
will not reproduce the full-data values reported in the paper.

To check data loading and the figures without fitting the models:

```bash
python src/analysis.py \
  --input data/sample_csi_data.csv \
  --output output_sample_eda \
  --skip-model
```

## Reproduce the full analysis

1. Download **Community Safety Indicators Open Data** from the Toronto Police
   Service Public Safety Data Portal:
   <https://data.tps.ca/datasets/TorontoPS::community-safety-indicators-open-data/about>
2. Save the CSV outside the submitted ZIP, or place it in `data/`.
3. Run:

```bash
python src/analysis.py \
  --input data/Community_Safety_Indicators_Open_Data.csv \
  --output output \
  --sample-output data/sample_csi_data.csv
```

The copy used for the paper contained 474,819 rows and 31 columns. The script
selects its 14 required fields by column name, so the CSV filename can differ
from the example above.

## Output files

- `dataset_summary.json`: row counts, class balance, years, and coordinate checks.
- `model_metrics.csv` and `model_metrics.json`: validation/test performance.
- `classification_report_*.json`: class-specific precision, recall, and F1.
- `figures/fig1_eda_overview.*`: class, annual, hourly, and premises EDA.
- `figures/fig_weekday_profile.*`: within-class weekday percentages.
- `figures/fig2_spatial_density.*`: category-specific spatial density.
- `figures/fig3_model_results.*`: confusion matrix and feature importance.

The script saves each figure as a PDF and a PNG.

## Methodological choices

- The unit of analysis is an offence/victim-level CSV row. Multiple rows may
  share an event ID, so figures are not interpreted as unique-incident counts.
- Records reported from 2014 through 2025 are analyzed. Partial 2026 data are
  excluded from annual comparisons and modeling.
- Models train on data from 2014 through 2023. The 2024 records are used for
  model selection, and the 2025 records form the chronological test set.
- `OFFENCE`, `UCR_CODE`, and `UCR_EXT` are excluded from predictors because they
  encode the target category and would cause label leakage.
- Invalid or suppressed coordinates remain in non-spatial summaries. The script
  treats them as missing during modeling and removes them from the maps.
- Fixed random seed `5430` makes sampling and model training reproducible.

## Data responsibility

The project uses only the open dataset published by the Toronto Police Service.
It records reported occurrences, not all victimization. This analysis does not
estimate causal risk or judge the safety of individuals. Its maps aggregate the
approximate coordinates in the source data; they are not exact addresses or
predictions about people.
