From 3cfdfe8a7ce15900c862f063df4ba50a9dba4a2b Mon Sep 17 00:00:00 2001
From: Mikhail Sirenko
Date: Thu, 26 Sep 2024 15:56:00 +0200
Subject: [PATCH] Major refactoring and update to v0.4.0
---
.github/workflows/docs.yml | 4 +-
.gitignore | 53 +-
CONTRIBUTING.md | 93 +
README.md | 229 +-
config/Example.yaml | 111 +
config/Nigeria.yaml | 138 --
.../asset_impacts/Example/earthquake.csv | 257 +++
.../processed/asset_impacts/Example/flood.csv | 257 +++
.../asset_impacts/Example/hurricane.csv | 257 +++
data/processed/household_survey/Example.csv | 101 +
docs/index.html | 7 -
docs/search.js | 46 -
docs/src.html | 234 --
docs/src/data.html | 241 --
docs/src/data/analyse.html | 876 --------
docs/src/data/prepare.html | 1984 -----------------
docs/src/data/read.html | 482 ----
docs/src/data/visualise.html | 1190 ----------
docs/src/data/write.html | 992 ---------
docs/src/model.html | 580 -----
docs/src/modules.html | 238 --
docs/src/modules/households.html | 1380 ------------
docs/src/modules/optimize.html | 779 -------
experiments/config_manager.py | 102 -
experiments/experiment_runner.py | 44 -
experiments/model_setup.py | 48 -
main.py | 36 -
requirements.txt | 305 ++-
sensitivity-analysis.ipynb | 362 ---
setup.py | 10 +-
unbreakable/__init__.py | 2 +-
unbreakable/analysis/analyzer.py | 472 ----
unbreakable/analysis/calculator.py | 281 ---
.../analysis/distributional_metrics.py | 168 ++
unbreakable/analysis/economic_metrics.py | 56 +
unbreakable/analysis/metric_calculator.py | 106 +
unbreakable/analysis/outcomes.yaml | 28 -
unbreakable/analysis/poverty_metrics.py | 193 ++
unbreakable/analysis/resilience_metrics.py | 69 +
unbreakable/analysis/verifier.py | 139 --
unbreakable/analysis/visualizer.py | 543 -----
unbreakable/data/generator.py | 82 -
unbreakable/data/randomizer.py | 522 -----
unbreakable/data/reader.py | 58 -
unbreakable/data/saver.py | 19 -
unbreakable/example.py | 46 +
.../experiments}/__init__.py | 0
unbreakable/experiments/config_handler.py | 146 ++
.../experiment_results_formatter.py | 124 ++
unbreakable/experiments/experiment_runner.py | 47 +
unbreakable/experiments/model_setup.py | 39 +
.../experiments/outcome_names_ordered.json | 1 +
unbreakable/main.py | 46 +
unbreakable/model.py | 237 +-
unbreakable/modules/disaster.py | 35 -
unbreakable/modules/disaster_impact.py | 339 +++
unbreakable/modules/dwelling_vulnerability.py | 147 ++
unbreakable/modules/household_recovery.py | 217 ++
unbreakable/modules/households.py | 148 --
unbreakable/modules/policy.py | 331 ---
.../policy_interventions.py} | 0
unbreakable/modules/recovery.py | 213 --
unbreakable/modules/socioeconomic_impact.py | 399 ++++
unbreakable/utils/__init__.py | 0
unbreakable/utils/data_estimator.py | 173 ++
unbreakable/utils/data_generator.py | 260 +++
unbreakable/utils/data_loader.py | 74 +
unbreakable/utils/data_matcher.py | 101 +
unbreakable/utils/data_randomizer.py | 198 ++
unbreakable/utils/data_resampler.py | 74 +
unbreakable/utils/data_validator.py | 97 +
.../utils/household_data_preprocessor.py | 177 ++
72 files changed, 5105 insertions(+), 12738 deletions(-)
create mode 100644 CONTRIBUTING.md
create mode 100644 config/Example.yaml
delete mode 100644 config/Nigeria.yaml
create mode 100644 data/processed/asset_impacts/Example/earthquake.csv
create mode 100644 data/processed/asset_impacts/Example/flood.csv
create mode 100644 data/processed/asset_impacts/Example/hurricane.csv
create mode 100644 data/processed/household_survey/Example.csv
delete mode 100644 docs/index.html
delete mode 100644 docs/search.js
delete mode 100644 docs/src.html
delete mode 100644 docs/src/data.html
delete mode 100644 docs/src/data/analyse.html
delete mode 100644 docs/src/data/prepare.html
delete mode 100644 docs/src/data/read.html
delete mode 100644 docs/src/data/visualise.html
delete mode 100644 docs/src/data/write.html
delete mode 100644 docs/src/model.html
delete mode 100644 docs/src/modules.html
delete mode 100644 docs/src/modules/households.html
delete mode 100644 docs/src/modules/optimize.html
delete mode 100644 experiments/config_manager.py
delete mode 100644 experiments/experiment_runner.py
delete mode 100644 experiments/model_setup.py
delete mode 100644 main.py
delete mode 100644 sensitivity-analysis.ipynb
delete mode 100644 unbreakable/analysis/analyzer.py
delete mode 100644 unbreakable/analysis/calculator.py
create mode 100644 unbreakable/analysis/distributional_metrics.py
create mode 100644 unbreakable/analysis/economic_metrics.py
create mode 100644 unbreakable/analysis/metric_calculator.py
delete mode 100644 unbreakable/analysis/outcomes.yaml
create mode 100644 unbreakable/analysis/poverty_metrics.py
create mode 100644 unbreakable/analysis/resilience_metrics.py
delete mode 100644 unbreakable/analysis/verifier.py
delete mode 100644 unbreakable/analysis/visualizer.py
delete mode 100644 unbreakable/data/generator.py
delete mode 100644 unbreakable/data/randomizer.py
delete mode 100644 unbreakable/data/reader.py
delete mode 100644 unbreakable/data/saver.py
create mode 100644 unbreakable/example.py
rename {experiments => unbreakable/experiments}/__init__.py (100%)
create mode 100644 unbreakable/experiments/config_handler.py
create mode 100644 unbreakable/experiments/experiment_results_formatter.py
create mode 100644 unbreakable/experiments/experiment_runner.py
create mode 100644 unbreakable/experiments/model_setup.py
create mode 100644 unbreakable/experiments/outcome_names_ordered.json
create mode 100644 unbreakable/main.py
delete mode 100644 unbreakable/modules/disaster.py
create mode 100644 unbreakable/modules/disaster_impact.py
create mode 100644 unbreakable/modules/dwelling_vulnerability.py
create mode 100644 unbreakable/modules/household_recovery.py
delete mode 100644 unbreakable/modules/households.py
delete mode 100644 unbreakable/modules/policy.py
rename unbreakable/{data/__init__.py => modules/policy_interventions.py} (100%)
delete mode 100644 unbreakable/modules/recovery.py
create mode 100644 unbreakable/modules/socioeconomic_impact.py
create mode 100644 unbreakable/utils/__init__.py
create mode 100644 unbreakable/utils/data_estimator.py
create mode 100644 unbreakable/utils/data_generator.py
create mode 100644 unbreakable/utils/data_loader.py
create mode 100644 unbreakable/utils/data_matcher.py
create mode 100644 unbreakable/utils/data_randomizer.py
create mode 100644 unbreakable/utils/data_resampler.py
create mode 100644 unbreakable/utils/data_validator.py
create mode 100644 unbreakable/utils/household_data_preprocessor.py
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index d2e62ec..4ea9e5a 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -23,7 +23,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
- python-version: '3.11'
+ python-version: '3.12.4'
# ADJUST THIS: install all dependencies (including pdoc)
- run: pip install pipreqs
@@ -52,4 +52,4 @@ jobs:
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
- uses: actions/deploy-pages@v2
+ uses: actions/deploy-pages@v2
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 0bc9d6d..8f94f6f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -77,15 +77,11 @@ target/
# exclude real data from source control by default
/data/raw
-/data/processed
/data/interim
/data/external
-# exclude figures until the paper is not on the arxiv
-/figures
-
-# exclude for now, keep later
-/features
+# exclude reports until the paper is not on the arxiv
+/reports
# Mac OS-specific storage files
.DS_Store
@@ -101,27 +97,38 @@ target/
.idea/
cache/
-# Raw country-specific experiment results
-experiments/Dominica
-experiments/Saint Lucia
+# exclude config files but keep Example.yaml
+/config/*
+!/config/Example.yaml
-# Internal reports
-/reports
+# exclude data_preparation from source control by default
+/data_preparation/*
+!/data_preparation/Example
-# Input data preparation scripts
-/scripts
+# exclude data_preparation from source control by default
+/data/generated/*
+!/data/generated/Example
-# Exclude Dominica-specific config
-/config/Dominica.yaml
+# exclude data but keep the Example folder or file
+/data/processed/asset_impacts/*
+!/data/processed/asset_impacts/Example
-# Exclude Saint-Lucia specific config
-/config/SaintLucia.yaml
+/data/processed/household_survey/*
+!/data/processed/household_survey/Example.csv
-# Exclude Nigeria specific config
-/config/Nigeria.yaml
+data/processed/population_impacts/*
+!/data/processed/population_impacts/Example
-# Exclude reports
-/reports
+# exclude drafts folder
+/drafts
+
+# exclude notebooks but keep the Example folder
+/notebooks/*
+!/notebooks/Example
+
+# exclude results and keep only the Example folder
+/results/*
+!/results/Example
-# Exclude experiment results
-/results
\ No newline at end of file
+# exlcude todo folder
+/todo
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..dc0525a
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,93 @@
+# Contributing
+
+We welcome contributions to the Unbreakable project! Whether you're fixing bugs, adding new features, improving documentation, or providing feedback, your help is appreciated.
+
+## How to Contribute
+
+### 1. Fork the Repository
+
+- Click the **Fork** button at the top right of the [repository page](https://github.com/mikhailsirenko/unbreakable) to create your own copy of the project.
+
+### 2. Clone Your Fork
+
+- Clone your forked repository to your local machine:
+
+ ```bash
+ git clone https://github.com/your-username/unbreakable.git
+ cd unbreakable
+ ```
+
+### 3. Create a New Branch
+
+- Create a new branch for your feature or bug fix:
+
+ ```bash
+ git checkout -b my-feature-branch
+ ```
+
+### 4. Make Changes
+
+- Implement your changes in the codebase.
+- Follow the existing code style and conventions.
+- Include comments and docstrings where appropriate.
+- Update or add documentation as needed.
+
+### 5. Commit Changes
+
+- Stage your changes and commit with a descriptive message:
+
+ ```bash
+ git add .
+ git commit -m "Description of your changes"
+ ```
+
+### 6. Push to Your Fork
+
+- Push your branch to your forked repository on GitHub:
+
+ ```bash
+ git push origin my-feature-branch
+ ```
+
+### 7. Submit a Pull Request
+
+- Go to the original repository and click on **Pull Requests**, then **New Pull Request**.
+- Select your branch from the **compare** dropdown.
+- Provide a clear and descriptive title and description for your pull request.
+- Submit the pull request for review.
+
+## Reporting Issues
+
+- If you encounter a bug or have a feature request, please open an [issue](https://github.com/mikhailsirenko/unbreakable/issues) on GitHub.
+- Provide detailed information about the issue, including steps to reproduce it if applicable.
+
+## Code Style Guidelines
+
+- Follow the existing coding style and structure.
+- Use meaningful variable and function names.
+- Keep functions and classes focused and concise.
+- Write tests for new features or bug fixes when possible.
+
+## Testing
+
+- Ensure that all existing tests pass before submitting a pull request.
+- Add new tests to cover your changes.
+- Run tests using:
+
+ ```bash
+ python -m unittest discover tests
+ ```
+
+## Documentation
+
+- Update the `README.md` or relevant documentation files if your changes affect them.
+- Ensure that code is well-documented with comments and docstrings.
+
+## Communication
+
+- Feel free to contact the project maintainers for guidance.
+- Be respectful and considerate in all interactions.
+
+## License
+
+By contributing to Unbreakable, you agree that your contributions will be licensed under Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0).
diff --git a/README.md b/README.md
index 36b279e..a33457e 100644
--- a/README.md
+++ b/README.md
@@ -1,46 +1,225 @@
-# What is unbreakable?
-Unbreakable is a stochastic simulation model for assessing the resilience of households to natural disasters.
+# unbreakable
-## Background
+Unbreakable is a simulation tool that helps estimate how disasters affect households, showing how different social groups recover and how policies can reduce the damage.
-## Model Overview
+## Motivation
-## Getting Started
+Natural disasters are becoming more frequent and intense, with a significant rise in events over recent decades. According to the [UNDRR](https://www.undrr.org/media/48008/download?startDownload=20240603), the number of recorded disasters nearly doubled from 4,212 between 1980-1999 to 7,348 between 2000-2019. In 2023, extreme weather events caused massive economic losses of 280 million USD ([PreventionWeb](https://www.preventionweb.net/news/europe-spotlight-global-economic-losses-catastrophes-reach-usd-280-billion-2023)) and impacted 93.1 million people globally ([EM-DAT](https://civil-protection-knowledge-network.europa.eu/media/2023-disasters-numbers-significant-year-disaster-impact)).
+
+Disasters do not affect all populations equally. Lower-income households are more vulnerable, as they often lack adequate resources for protection and recovery ([Bangalore et al., 2016](http://hdl.handle.net/10986/25335); [Walsh & Hallegatte, 2020](https://link.springer.com/article/10.1007/s41885-019-00047-x)). Vulnerable groups like female-headed households and people with disabilities are also disproportionately impacted.
+
+Beyond economic loss, disasters affect overall well-being, which isn’t fully captured by traditional metrics. To better understand these broader impacts, we need alternative approaches.
+
+Unbreakable is a simulation tool designed to:
+
+1. Estimate disaster impacts on different social groups.
+2. Analyze effects across economic, poverty, and well-being dimensions.
+3. Explore how policy interventions can reduce these impacts.
+
+## Project Structure
-### Prerequisites
-The model is developed in Python 3.9 and relies on standard packages. The easiest way to install them is to use [Anaconda](https://www.anaconda.com/products/individual) with the `requirements.txt` file:
```bash
-conda create --name unbreakable --file requirements.txt
+unbreakable/
+├── config/ # Simulation model run configuration files
+├── data/ # Data directory
+│ ├── generated/ # Generated data, e.g., pre-computed reconstruction rates
+│ ├── processed/ # Processed data used as an input into simulation model
+│ └── raw/ # Raw data
+├── data_preparation/ # Data preprocessing notebooks
+├── docs/ # Documentation
+├── notebooks/ # Analysis notebooks
+├── unbreakable/ # Main package
+│ ├── analysis/ # Analysis modules
+│ ├── experiments/ # Experiment setup and runner
+│ ├── modules/ # Core simulation modules
+│ └── utils/ # Utility functions mainly for data preparation
+├── results/ # Simulation results
+├── tests/ # Unit tests
+├── CONTRIBUTING.md # Guidelines for contributing to the project
+├── README.md # Project overview and instructions
+├── requirements.txt # List of dependencies
+└── setup.py # Installation script
```
-### Installation
-Clone the repository from GitHub using the following:
-```bash
-git clone https://github.com/mikhailsirenko/unbreakable
+## Installation
+
+1. Clone the repository:
+
+ ```bash
+ git clone https://github.com/mikhailsirenko/unbreakable.git
+ cd unbreakable
+ ```
+
+2. Create a virtual environment with conda (optional but recommended):
+
+ ```bash
+ conda create --name unbreakable
+ conda activate unbreakable
+ ```
+
+3. Install dependencies:
+
+ ```bash
+ pip install -r requirements.txt
+ ```
+
+4. Install the package in editable mode:
+
+ ```bash
+ pip install -e .
+ ```
+
+## Basic Usage
+
+To run a simulation:
+
+```python
+python unbreakable/example.py
```
-### Repository Structure
+The `example.py` script requires specifying disaster types, their timing (immediate or at a specific year, e.g., year 5), and return periods. By default, `example.py` simulates the immediate impact of a flood with a return period of 100 years.
+You also need to specify the number of replications with `n_scenarios`. The model is stochastic, and to obtain robust results, multiple replications are necessary. In each run, the model randomly selects which households are affected and the amount of assets they lose. By default, `n_scenarios = 1,000`.
-### Usage
-You run the model from the command line with the default parameters using:
-```bash
-python unbreakable/run.py
+For a more comprehensive description, please refer to the User Manual or the detailed documentation in the `docs/` directory.
+
+## Data
+
+The model uses three main types of data:
+
+1. Household survey data (`data/processed/household_survey/`),
+2. Asset impact data (`data/processed/asset_impact/`), or
+3. Population impact data (`data/processed/population_impacts/`)
+
+Household survey data contains information on households' socio-economic attributes and dwelling materials. Asset impact data provides information about potential damage to total assets of a spatial unit (e.g., a district). Population impacts data contains information about the number of individuals affected by a disaster.
+
+The repository contains example data of all types which were generated with `unbreakable/utils/data_generator.py`.
+
+## Configuration
+
+Simulations are configured using YAML files in the `config/` directory. The `Example.yaml` file provides an example configuration. You can modify this file to set up your simulation parameters, including:
+
+- Macro-economic parameters of the case country.
+- Disaster-related parameters, including whether households would lose their income due to disaster.
+- Which household characteristics must be estimated and randomized.
+- Policy interventions, e.g., adaptive social protection.
+- Uncertainties.
+
+## Model Components
+
+The core model components are located in the `unbreakable/modules/` directory:
+
+- `disaster_impact.py`: Simulates disaster impacts on households.
+- `dwelling_vulnerability.py`: Calculates dwelling vulnerability based on construction materials.
+- `household_recovery.py`: Models household recovery processes over time.
+- `policy_interventions.py`: Implements policy interventions such as cash transfers or retrofitting.
+- `socioeconomic_impact.py`: Assesses economic, poverty, and well-being impacts.
+
+## How It Works
+
+The Unbreakable Model stored in `model.py` follows a step-by-step process to simulate disaster events and their impacts. The basic idea is that we pass the households' data frame through a set of functions representing different stages of the simulation. The pipeline works as follows:
+
+1. **Data Loading and Preparation**:
+ - Load household data, disaster impact data, and reconstruction rates.
+ - Prepare the household data, estimate missing attributes (e.g., savings) and randomize them.
+
+2. **Disaster Impact Calculation**:
+ - Calculate compound impacts if multiple disaster events are specified.
+ - Determine the years until the next event for each disaster.
+
+3. **Spatial Unit Iteration**:
+ - The model iterates over each specified spatial unit (e.g., regions, cities).
+
+4. **Disaster Event Simulation**:
+ - For each spatial unit, the model simulates multiple disaster events sequentially.
+ - Each event's impact is calculated based on either the percentage of population affected or Probable Maximum Loss (PML).
+
+5. **Household Impact Distribution**:
+ - The disaster impact is distributed among households based on their vulnerability.
+ - Households are classified as affected or unaffected.
+
+6. **Recovery Simulation**:
+ - Calculate or use precomputed household reconstruction rates.
+ - Estimate the socioeconomic impact on households, including consumption, poverty and well-being losses.
+
+7. **Policy Interventions**:
+ - The model allows for the application of policy interventions, such as adaptive social protection or retrofitting policies.
+
+8. **Cumulative Impact Tracking**:
+ - The model keeps track of cumulative impacts across multiple events.
+
+9. **Outcome Calculation**:
+ - Calculate various metrics for each spatial unit after all events have been simulated.
+
+This pipeline allows for the simulation of multiple disasters over time, assessment of cumulative impacts, and evaluation of policy interventions at various stages.
+
+```mermaid
+graph TD
+ A[Start] --> B[Load and Prepare Data]
+ B --> C[Calculate Compound Impact]
+ C --> D[Calculate Years Until Next Event]
+ D --> E[Iterate Over Spatial Units]
+ E --> F[Iterate Over Disaster Events]
+ F --> G[Simulate Disaster]
+ G --> H[Apply Policy Interventions]
+ H --> I[Estimate Socioeconomic Impact]
+ I --> J[Update Cumulative Impact]
+ J --> K{More Events?}
+ K -->|Yes| F
+ K -->|No| L[Calculate Outcomes for Spatial Unit]
+ L --> M{More Spatial Units?}
+ M -->|Yes| E
+ M -->|No| N[End]
+
+ subgraph Simulate Disaster
+ G1[Calculate Dwelling Vulnerability]
+ G2[Distribute Disaster Impact]
+ G3[Determine Affected Households]
+ G4[Calculate Reconstruction Rates]
+ G1 --> G2 --> G3 --> G4
+ end
```
-## Documentation
-Detailed model documentation, including function descriptions and usage examples, is available [here](https://mikhailsirenko.github.io/unbreakable/src.html).
+## Analysis
+
+Analysis modules in `unbreakable/analysis/` include:
+
+- `distributional_metrics.py`: Analyzes impacts across different groups
+- `economic_metrics.py`: Calculates economic impact metrics
+- `metric_calculator.py`: Analyzes household-level impacts
+- `poverty_metrics.py`: Computes poverty-related metrics
+- `resilience_metrics.py`: Calculates resilience indicators
+
+Jupyter notebooks for analysis are available in the `notebooks/` directory. These notebooks demonstrate how to interpret the simulation outcomes and visualize results.
+
+## Results
+
+Simulation results are stored in the `results/` directory. The `Example/` subdirectory contains example results.
+
+## Note for Users
+
+This model uses algorithms and data analysis techniques. While it strives for accuracy, real-world scenarios may differ. Use the results only as a guide for decision-making, always complemented by expert knowledge and local context.
## Contributing
-## Authors
-*Mikhail Sirenko* and *Bramka Arga Jafino*.
+We welcome contributions to the Unbreakable project. Please refer to our [`CONTRIBUTING.md`](CONTRIBUTING.md) for information on submitting pull requests, reporting issues, or suggesting improvements.
## License
-The project license is CC BY 3.0 IGO.
+
+This project is licensed under Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0).
+
+## Citation
+
+1. If you use this tool in your research, please cite it as:
+
+ Sirenko, M. & Jafino, B. A. (2024). Unbreakable: A Simulation Tool for Estimating Socio-Economic Impacts of Disaster on Households. GitHub repository:
+
+2. The original World Bank report and research paper:
+
+ Bangalore, M., Hallegatte, S., Vogt-Schilb, A., Rozenberg, J. (2017). Unbreakable: Building the Resilience of the Poor in the Face of Natural Disasters. Climate Change and Development. Washington, DC: World Bank. .
+
+ Walsh, B., & Hallegatte, S. (2020). Measuring natural risks in the Philippines: Socioeconomic resilience and wellbeing losses. Economics of Disasters and Climate Change, 4(2), 249-293.
## Contact
-For inquiries or collaboration, feel free to reach out to [Mikhail Sirenko](https://twitter.com/mikhailsirenko).
-## References
-Hallegatte, S., Vogt-Schilb, A., Bangalore, M., & Rozenberg, J. (2017). *Unbreakable: Building the Resilience of the Poor in the Face of Natural Disasters*. Climate Change and Development. Washington, DC: World Bank. [http://hdl.handle.net/10986/25335](http://hdl.handle.net/10986/25335)
\ No newline at end of file
+For questions or feedback, please contact Mikhail Sirenko at msirenko at worldbank.org.
diff --git a/config/Example.yaml b/config/Example.yaml
new file mode 100644
index 0000000..7f7d243
--- /dev/null
+++ b/config/Example.yaml
@@ -0,0 +1,111 @@
+# --------------------------------- Constants -------------------------------- #
+constants:
+ country: Example
+
+ # Each spatial unit has an array of outcomes that are calculated for it
+ spatial_units:
+ - region_1
+ - region_2
+ - region_3
+
+ # Global economic parameters specific to the country
+ economic_params:
+ average_productivity: 0.25 # average of cgdpo / cn for the last 5 years from the Penn World Table https://www.rug.nl/ggdc/productivity/pwt/?lang=en
+ income_and_expenditure_growth: 0.02 # assumption source: ?
+ consumption_utility: 1.5 # assumption source: Hallegatte et al. (2017) choose a standard value of 1.5 to represent the elasticity of the marginal utility of consumption
+ discount_rate: 0.04 # assumption source: ?
+
+ # Recovery parameters
+ recovery_params:
+ use_precomputed_reconstruction_rates: true
+ lambda_increment: 0.01
+ max_years: 10
+
+ # Disaster parameters
+ disaster_params:
+ impact_data_type: assets # population or assets
+ disaster_impact_params:
+ add_income_loss: true
+ poverty_bias_factor: 1.0
+ distribution: uniform
+ max_bias: 1.5
+ min_bias : 0.5
+ determine_affected_params:
+ loss_margin_pct: 0.05
+ max_random_threshold: 1.0
+ min_random_threshold: 0
+ num_simulations: 10000
+
+ # Estimation and randomization parameters
+ income_params:
+ estimate: true
+ randomize: true
+ distribution: uniform
+ inc_exp_ratio: 1.3 # assumption source?
+ delta: 0.1 # absolute deviation from the base income to expenditure ratio
+ savings_params:
+ estimate: true
+ randomize: true
+ cap_with_max_savings_rate: false # whether to cap the savings rate with the maximum savings rate
+ distribution: uniform
+ delta: 0.01 # absolute deviation from the base savings rate
+ max_savings_rate: 0.1 # maximum savings rate to prevent unrealistic values during randomization
+ rent_params:
+ estimate: true
+ randomize: true
+ distribution: uniform
+ pct_of_income: 0.14 # assumption source?
+ delta: 0.05 # absolute deviation from the base rent as a percentage of income
+ dwelling_vulnerability_params:
+ randomize: true
+ distribution: uniform
+ low: 0.9
+ high: 1.1
+ min_threshold: 0.2 # with vulnerability <= 0.13, recovery rate can be up to 5
+ max_threshold: 0.9 # with vulnerability >= 0.98, recovery rate skyrockets to 10
+
+ min_households: 10000
+ atol: 100000
+
+ # Analysis parameters
+ analysis_params:
+ save_households: false
+ save_consumption_recovery: false
+ distributional_impacts: true
+ socioeconomic_attributes:
+ - female_headed
+ - urban
+ - literacy
+
+
+# ------------------------------- Policy levers ------------------------------ #
+# ASP: Adaptive social protection
+# The naming convention is: +
+# The following target groups are currently specified: all, poor, poor_near_poor1.25, poor_near_poor2.0
+# There are no limitations on the top-up percentage
+
+# Retrofitting: Retrofitting of vulnerable houses
+# The naming convention is:
+# The following levels are currently specified: Basic, Intermediate, Advanced
+# Currently, the retrofitting is available only for Dominica
+
+# levers:
+# 0: none
+# 1: asp:all+10
+# 2: asp:all+30
+# 3: asp:all+50
+# 4: asp:poor+10
+# 5: asp:poor+30
+# 6: asp:poor+50
+# 7: asp:poor_near_poor1.25+10
+# 8: asp:poor_near_poor1.25+30
+# 9: asp:poor_near_poor1.25+50
+# 10: asp:poor_near_poor2.0+10
+# 11: asp:poor_near_poor2.0+30
+# 12: asp:poor_near_poor2.0+50
+
+# ------------------------------- Uncertainties ------------------------------ #
+uncertainties:
+
+# References
+# 1. Hallegatte,Stephane; Vogt-Schilb,Adrien Camille; Bangalore,Mook; Rozenberg,Julie. Unbreakable: building the resilience of the poor in the face of natural disasters (English). Climate Change and Development Washington, D.C.: World Bank Group. http://documents.worldbank.org/curated/en/512241480487839624/Unbreakable-building-the-resilience-of-the-poor-in-the-face-of-natural-disasters
\ No newline at end of file
diff --git a/config/Nigeria.yaml b/config/Nigeria.yaml
deleted file mode 100644
index 194c35d..0000000
--- a/config/Nigeria.yaml
+++ /dev/null
@@ -1,138 +0,0 @@
-# --------------------------------- Constants -------------------------------- #
-constants:
- # Case study params
- country: Nigeria
- regions:
- - 'Abia'
- - 'Abuja Federal Capital Territory'
- - 'Adamawa'
- - 'Akwa Ibom'
- - 'Anambra'
- - 'Bauchi'
- - 'Bayelsa'
- - 'Benue'
- - 'Cross River'
- - 'Delta'
- - 'Ebonyi'
- - 'Edo'
- - 'Ekiti'
- - 'Enugu'
- - 'Gombe'
- - 'Imo'
- - 'Jigawa'
- - 'Kaduna'
- - 'Kano'
- - 'Katsina'
- - 'Kebbi'
- - 'Kogi'
- - 'Kwara'
- - 'Lagos'
- - 'Nasarawa'
- - 'Niger'
- - 'Ogun'
- - 'Ondo'
- - 'Osun'
- - 'Oyo'
- - 'Plateau'
- - 'Rivers'
- - 'Sokoto'
- - 'Taraba'
- - 'Yobe'
- - 'Zamfara'
- avg_prod: 0.35
- inc_exp_growth: 0.02
- cons_util: 1.5
- disc_rate: 0.04
- is_conflict: False
-
- # Disaster params
- disaster_type: flood
- return_per: 10
- calc_exposure_params:
- distr: uniform
- high: 1.5
- low: 0.5
- identify_aff_params:
- delta_pct: 0.05
- distr: uniform
- high: 1.0
- low: 0
- num_masks: 10000
-
- # Recovery params
- add_inc_loss: True
- pov_bias: 1.0
- lambda_incr: 0.01
- yrs_to_rec: 10
-
- # Randmoziation params
- rnd_house_vuln_params:
- randomize: True
- distr: uniform
- low: 0.8
- high: 1.2
- thresh: 0.9
- rnd_inc_params:
- randomize: True
- distr: uniform
- delta: 0.1
- rnd_sav_params:
- randomize: True
- distr: uniform
- avg: 0.0204
- delta: 0.02
- rnd_rent_params:
- randomize: True
- distr: uniform
- avg: 0.43 # Assumption source: https://livingcost.org/cost/dominica
- delta: 0.1
- min_households: 5000
- atol: 100000
-
- # Misc params
- save_households: False
- save_consumption_recovery: True
-
-# ------------------------------- Policy levers ------------------------------ #
-# The naming convention is: +
-# The following target groups are currently specified: all, poor, poor_near_poor1.25, poor_near_poor2.0
-# There are no limitations on the top-up percentage
-# Top-up percentage is added to `aeexp` or adult equivalent expenditure of a household
-# It is applied as a multiplier to `keff*v`: households['aeexp'] += households.eval('keff*v') * top_up / 100
-# where `v` is the vulnerability of the household and `keff` is the effective capital stock
-levers:
- 0: all+0
- 1: all+10
- 2: all+30
- 3: all+50
- 4: all+100
- 5: poor+0
- 6: poor+10
- 7: poor+30
- 8: poor+50
- 9: poor+100
- 10: poor_near_poor1.25+0
- 11: poor_near_poor1.25+10
- 12: poor_near_poor1.25+30
- 13: poor_near_poor1.25+50
- 14: poor_near_poor1.25+100
- 15: poor_near_poor2.0+0
- 16: poor_near_poor2.0+10
- 17: poor_near_poor2.0+30
- 18: poor_near_poor2.0+50
- 19: poor_near_poor2.0+100
-
-# ------------------------------- Uncertainties ------------------------------ #
-uncertainties:
- avg_prod:
- - 0.2
- - 0.4
- cons_util:
- - 1.0
- - 1.5
- disc_rate:
- - 0.04
- - 0.07
- inc_exp_growth:
- - 0.01
- - 0.03
\ No newline at end of file
diff --git a/data/processed/asset_impacts/Example/earthquake.csv b/data/processed/asset_impacts/Example/earthquake.csv
new file mode 100644
index 0000000..8283229
--- /dev/null
+++ b/data/processed/asset_impacts/Example/earthquake.csv
@@ -0,0 +1,257 @@
+disaster_type,spatial_unit,residential,non_residential,total_exposed_stock,rp,pml,loss_fraction
+earthquake,region_0,687270.06,487678.58,1174948.64,10,219949.67,0.187
+earthquake,region_1,799329.24,289004.66,1088333.9,10,163250.09,0.15
+earthquake,region_2,529041.81,466544.04,995585.84,10,173342.95,0.174
+earthquake,region_3,854036.29,255146.12,1109182.41,10,234027.49,0.211
+earthquake,region_4,916221.32,303084.78,1219306.1,10,182895.91,0.15
+earthquake,region_5,591702.25,326060.56,917762.82,10,152785.16,0.166
+earthquake,region_6,715972.51,322807.29,1038779.79,10,181978.94,0.175
+earthquake,region_7,569746.93,323036.16,892783.09,10,134485.44,0.151
+earthquake,region_8,728034.99,446293.99,1174328.98,10,176149.35,0.15
+earthquake,region_9,757117.22,398103.64,1155220.86,10,173283.13,0.15
+earthquake,region_10,803772.43,292631.03,1096403.46,10,164460.52,0.15
+earthquake,region_11,974442.77,491408.01,1465850.78,10,285605.98,0.195
+earthquake,region_12,652306.88,274418.03,926724.91,10,169056.22,0.182
+earthquake,region_13,720076.25,280509.56,1000585.81,10,163613.48,0.164
+earthquake,region_14,517194.26,477330.1,994524.36,10,149178.65,0.15
+earthquake,region_15,831261.14,327927.77,1159188.91,10,192433.24,0.166
+earthquake,region_16,773355.14,296213.61,1069568.75,10,225634.58,0.211
+earthquake,region_17,887566.41,484874.74,1372441.15,10,279268.08,0.203
+earthquake,region_18,798949.99,480468.56,1279418.55,10,191912.78,0.15
+earthquake,region_19,597991.43,261306.82,859298.25,10,128894.74,0.15
+earthquake,region_20,694338.64,317837.26,1012175.9,10,199270.87,0.197
+earthquake,region_21,678376.66,320233.63,998610.29,10,168035.76,0.168
+earthquake,region_22,570462.11,450549.25,1021011.36,10,153151.7,0.15
+earthquake,region_23,993443.47,443061.19,1436504.66,10,215475.7,0.15
+earthquake,region_24,502761.06,453865.36,956626.42,10,176675.25,0.185
+earthquake,region_25,864503.58,442817.59,1307321.17,10,196098.18,0.15
+earthquake,region_26,679232.86,278967.26,958200.13,10,191937.4,0.2
+earthquake,region_27,811649.06,332724.51,1144373.57,10,171656.04,0.15
+earthquake,region_28,655491.16,331295.83,986786.99,10,184490.31,0.187
+earthquake,region_29,818778.74,471803.19,1290581.92,10,208069.54,0.161
+earthquake,region_30,559797.12,428311.2,988108.32,10,187818.15,0.19
+earthquake,region_31,780638.6,442741.79,1223380.39,10,199875.35,0.163
+earthquake,region_32,761366.41,356885.25,1118251.67,10,167737.75,0.15
+earthquake,region_33,553945.71,257857.3,811803.01,10,144209.53,0.178
+earthquake,region_34,657177.99,377142.67,1034320.66,10,211784.03,0.205
+earthquake,region_35,624646.11,352595.73,977241.85,10,185241.19,0.19
+earthquake,region_36,614399.08,269244.98,883644.06,10,132546.61,0.15
+earthquake,region_37,580610.64,482424.41,1063035.06,10,207092.03,0.195
+earthquake,region_38,816701.88,467865.15,1284567.03,10,249677.71,0.194
+earthquake,region_39,593285.03,473139.75,1066424.78,10,179089.22,0.168
+earthquake,region_40,903720.08,474022.82,1377742.9,10,206661.44,0.15
+earthquake,region_41,555025.96,306983.79,862009.75,10,135086.22,0.157
+earthquake,region_42,909007.38,465182.65,1374190.03,10,206128.5,0.15
+earthquake,region_43,755373.65,354352.75,1109726.4,10,166458.96,0.15
+earthquake,region_44,559932.68,334403.79,894336.48,10,186282.21,0.208
+earthquake,region_45,661601.47,379697.66,1041299.12,10,191913.4,0.184
+earthquake,region_46,681814.8,492945.52,1174760.32,10,246987.17,0.21
+earthquake,region_47,625891.15,374312.13,1000203.27,10,150030.49,0.15
+earthquake,region_48,642420.25,259221.74,901641.98,10,157748.07,0.175
+earthquake,region_49,751339.51,262869.69,1014209.2,10,152131.38,0.15
+earthquake,region_50,954132.94,309890.47,1264023.42,10,189603.51,0.15
+earthquake,region_51,744726.38,496412.61,1241138.99,10,186170.85,0.15
+earthquake,region_52,836067.77,440404.9,1276472.68,10,191470.9,0.15
+earthquake,region_53,864108.17,341945.78,1206053.96,10,213749.65,0.177
+earthquake,region_54,816764.86,383943.67,1200708.53,10,180106.28,0.15
+earthquake,region_55,917651.25,330195.02,1247846.26,10,187176.94,0.15
+earthquake,region_56,520387.57,397723.24,918110.81,10,166872.55,0.182
+earthquake,region_57,508293.91,378023.26,886317.18,10,132947.58,0.15
+earthquake,region_58,822586.4,293591.61,1116178.0,10,204365.24,0.183
+earthquake,region_59,693367.67,484182.5,1177550.17,10,176632.53,0.15
+earthquake,region_60,670533.18,278368.38,948901.56,10,195919.1,0.206
+earthquake,region_61,938669.68,314485.41,1253155.08,10,225565.92,0.18
+earthquake,region_62,908611.1,388800.2,1297411.3,10,216622.35,0.167
+earthquake,region_63,620926.15,273275.69,894201.84,10,182168.21,0.204
+earthquake,region_0,950209.03,408275.36,1358484.39,50,276999.01,0.204
+earthquake,region_1,674604.79,431488.92,1106093.71,50,287264.73,0.26
+earthquake,region_2,943543.21,444968.89,1388512.1,50,325193.93,0.234
+earthquake,region_3,542069.98,290407.18,832477.16,50,216323.7,0.26
+earthquake,region_4,803214.53,252299.26,1055513.79,50,190147.81,0.18
+earthquake,region_5,831750.88,251265.4,1083016.28,50,201528.54,0.186
+earthquake,region_6,774366.89,422973.8,1197340.69,50,281609.89,0.235
+earthquake,region_7,612134.65,428044.81,1040179.46,50,201508.67,0.194
+earthquake,region_8,662699.85,436622.85,1099322.7,50,258300.48,0.235
+earthquake,region_9,924611.71,414403.22,1339014.93,50,303729.91,0.227
+earthquake,region_10,546837.38,341928.95,888766.33,50,174660.57,0.197
+earthquake,region_11,621994.82,493252.64,1115247.46,50,233432.19,0.209
+earthquake,region_12,946023.28,407784.66,1353807.93,50,337749.53,0.249
+earthquake,region_13,751318.55,394225.97,1145544.52,50,251162.66,0.219
+earthquake,region_14,597621.49,430613.03,1028234.52,50,203669.85,0.198
+earthquake,region_15,512157.98,411368.07,923526.06,50,173356.06,0.188
+earthquake,region_16,970229.29,488482.14,1458711.44,50,381433.26,0.261
+earthquake,region_17,685079.35,253864.15,938943.5,50,246784.26,0.263
+earthquake,region_18,714092.07,491663.7,1205755.78,50,321167.52,0.266
+earthquake,region_19,926504.73,323612.22,1250116.95,50,260661.6,0.209
+earthquake,region_20,925568.34,329230.5,1254798.84,50,234583.73,0.187
+earthquake,region_21,778400.63,484038.69,1262439.32,50,302484.22,0.24
+earthquake,region_22,785030.59,274294.12,1059324.71,50,245234.44,0.232
+earthquake,region_23,995026.93,285021.0,1280047.93,50,283956.83,0.222
+earthquake,region_24,938686.54,435192.15,1373878.69,50,329320.88,0.24
+earthquake,region_25,851242.04,339872.79,1191114.83,50,237459.68,0.199
+earthquake,region_26,904680.58,452528.35,1357208.93,50,348405.35,0.257
+earthquake,region_27,956620.28,377835.6,1334455.88,50,293782.64,0.22
+earthquake,region_28,899147.59,412490.98,1311638.57,50,315051.24,0.24
+earthquake,region_29,897896.33,472501.34,1370397.67,50,279286.38,0.204
+earthquake,region_30,687791.48,273495.48,961286.96,50,219008.1,0.228
+earthquake,region_31,517971.14,366399.5,884370.64,50,198332.91,0.224
+earthquake,region_32,643270.63,397708.32,1040978.94,50,180141.43,0.173
+earthquake,region_33,518674.09,455650.14,974324.23,50,200729.37,0.206
+earthquake,region_34,563530.26,380560.82,944091.07,50,233189.89,0.247
+earthquake,region_35,607910.51,405722.62,1013633.13,50,180968.73,0.179
+earthquake,region_36,525840.86,382838.66,908679.52,50,203601.92,0.224
+earthquake,region_37,818714.95,431522.83,1250237.78,50,334545.14,0.268
+earthquake,region_38,758150.17,330739.12,1088889.29,50,271698.15,0.25
+earthquake,region_39,635416.13,359742.86,995158.98,50,176984.68,0.178
+earthquake,region_40,512675.37,490662.1,1003337.48,50,254444.39,0.254
+earthquake,region_41,847987.1,352238.24,1200225.34,50,224837.53,0.187
+earthquake,region_42,578218.52,312560.72,890779.25,50,200356.44,0.225
+earthquake,region_43,857297.96,415049.34,1272347.31,50,251916.36,0.198
+earthquake,region_44,977432.64,434474.23,1411906.87,50,318293.8,0.225
+earthquake,region_45,805860.37,354900.02,1160760.39,50,226084.9,0.195
+earthquake,region_46,677986.34,439461.53,1117447.87,50,191574.53,0.171
+earthquake,region_47,558036.32,261500.66,819536.98,50,142659.16,0.174
+earthquake,region_48,927730.29,425914.46,1353644.76,50,294305.9,0.217
+earthquake,region_49,548917.08,372903.97,921821.05,50,200355.2,0.217
+earthquake,region_50,586600.93,358462.91,945063.85,50,198322.1,0.21
+earthquake,region_51,807925.05,408773.41,1216698.46,50,212350.87,0.175
+earthquake,region_52,687306.31,406464.98,1093771.29,50,240972.72,0.22
+earthquake,region_53,928244.92,414673.41,1342918.33,50,250176.88,0.186
+earthquake,region_54,535284.37,410604.82,945889.19,50,163308.84,0.173
+earthquake,region_55,792887.79,485057.56,1277945.35,50,290793.16,0.228
+earthquake,region_56,694084.96,410822.05,1104907.02,50,238466.88,0.216
+earthquake,region_57,772808.39,485366.2,1258174.6,50,262468.13,0.209
+earthquake,region_58,980595.28,476337.66,1456932.94,50,276204.06,0.19
+earthquake,region_59,534680.65,275194.5,809875.15,50,139154.52,0.172
+earthquake,region_60,547221.48,420751.69,967973.17,50,171446.31,0.177
+earthquake,region_61,659487.82,461218.83,1120706.64,50,193128.23,0.172
+earthquake,region_62,907234.24,320463.69,1227697.93,50,223215.72,0.182
+earthquake,region_63,848368.58,407235.71,1255604.29,50,323628.49,0.258
+earthquake,region_0,867535.52,450870.23,1318405.75,100,353600.98,0.268
+earthquake,region_1,588719.77,437653.69,1026373.46,100,329141.01,0.321
+earthquake,region_2,995252.57,353154.42,1348406.99,100,373780.86,0.277
+earthquake,region_3,888206.48,335200.89,1223407.37,100,407487.3,0.333
+earthquake,region_4,929206.38,357248.51,1286454.88,100,405345.35,0.315
+earthquake,region_5,877271.44,275780.97,1153052.4,100,380801.66,0.33
+earthquake,region_6,752626.19,456614.37,1209240.55,100,328919.43,0.272
+earthquake,region_7,947761.61,347300.42,1295062.03,100,312218.43,0.241
+earthquake,region_8,952690.99,272821.67,1225512.66,100,333255.33,0.272
+earthquake,region_9,975030.98,487651.79,1462682.77,100,434919.64,0.297
+earthquake,region_10,815918.61,362111.38,1178029.99,100,317268.3,0.269
+earthquake,region_11,664332.27,418129.61,1082461.89,100,341232.53,0.315
+earthquake,region_12,895789.52,447404.54,1343194.06,100,334617.32,0.249
+earthquake,region_13,747210.15,264389.69,1011599.84,100,298374.3,0.295
+earthquake,region_14,720765.25,471926.05,1192691.3,100,328099.24,0.275
+earthquake,region_15,558533.51,285747.92,844281.43,100,266920.47,0.316
+earthquake,region_16,809109.03,275280.67,1084389.7,100,269373.98,0.248
+earthquake,region_17,850484.57,268190.75,1118675.32,100,360421.53,0.322
+earthquake,region_18,853121.11,270337.2,1123458.31,100,279161.16,0.248
+earthquake,region_19,993319.79,343567.7,1336887.49,100,370403.68,0.277
+earthquake,region_20,906399.78,486812.14,1393211.93,100,471741.71,0.339
+earthquake,region_21,876689.09,344064.9,1220753.99,100,303174.34,0.248
+earthquake,region_22,888573.46,389601.06,1278174.52,100,360984.86,0.282
+earthquake,region_23,953177.19,277799.37,1230976.56,100,356075.37,0.289
+earthquake,region_24,505676.82,367165.16,872841.98,100,214396.46,0.246
+earthquake,region_25,559408.96,279381.56,838790.52,100,255764.87,0.305
+earthquake,region_26,873022.44,395842.19,1268864.63,100,426614.18,0.336
+earthquake,region_27,687435.29,321428.02,1008863.31,100,329756.97,0.327
+earthquake,region_28,611797.92,490805.63,1102603.55,100,265965.01,0.241
+earthquake,region_29,984939.41,260789.98,1245729.39,100,409987.37,0.329
+earthquake,region_30,763850.55,498241.2,1262091.75,100,312215.82,0.247
+earthquake,region_31,776927.14,492325.63,1269252.78,100,371015.01,0.292
+earthquake,region_32,814699.32,423937.17,1238636.49,100,353573.87,0.285
+earthquake,region_33,813779.04,396078.58,1209857.62,100,399393.12,0.33
+earthquake,region_34,522723.19,320240.8,842963.99,100,282427.62,0.335
+earthquake,region_35,945131.89,363914.19,1309046.08,100,395349.27,0.302
+earthquake,region_36,638690.59,297030.29,935720.88,100,267962.24,0.286
+earthquake,region_37,676676.11,395914.03,1072590.14,100,265759.37,0.248
+earthquake,region_38,987197.4,496552.69,1483750.09,100,459689.77,0.31
+earthquake,region_39,768048.18,327381.9,1095430.09,100,352048.78,0.321
+earthquake,region_40,842365.59,290654.23,1133019.82,100,375134.61,0.331
+earthquake,region_41,911268.62,487449.98,1398718.6,100,437200.2,0.313
+earthquake,region_42,806707.6,354560.76,1161268.36,100,387019.21,0.333
+earthquake,region_43,933031.94,261304.67,1194336.61,100,289789.89,0.243
+earthquake,region_44,688231.68,452638.33,1140870.02,100,386444.18,0.339
+earthquake,region_45,575208.45,398532.68,973741.12,100,270786.78,0.278
+earthquake,region_46,984957.2,460529.73,1445486.93,100,468096.18,0.324
+earthquake,region_47,734346.58,353704.88,1088051.46,100,290880.45,0.267
+earthquake,region_48,528187.75,466180.59,994368.34,100,319480.71,0.321
+earthquake,region_49,999858.84,499159.21,1499018.05,100,443024.55,0.296
+earthquake,region_50,884493.71,486191.43,1370685.14,100,445424.34,0.325
+earthquake,region_51,623674.05,362636.03,986310.08,100,249453.54,0.253
+earthquake,region_52,977025.51,401543.66,1378569.17,100,362376.59,0.263
+earthquake,region_53,835850.34,404532.06,1240382.4,100,342117.65,0.276
+earthquake,region_54,556778.8,417893.3,974672.09,100,284634.24,0.292
+earthquake,region_55,886159.2,380040.88,1266200.07,100,411791.24,0.325
+earthquake,region_56,775953.42,390234.49,1166187.91,100,382119.38,0.328
+earthquake,region_57,701741.43,283503.81,985245.24,100,239294.66,0.243
+earthquake,region_58,877568.63,405077.39,1282646.02,100,398143.55,0.31
+earthquake,region_59,606482.08,284092.87,890574.95,100,215033.3,0.241
+earthquake,region_60,675293.78,397479.42,1072773.2,100,299544.46,0.279
+earthquake,region_61,718737.46,476039.67,1194777.13,100,328355.28,0.275
+earthquake,region_62,756994.74,445913.25,1202908.0,100,336398.37,0.28
+earthquake,region_63,811043.35,465590.93,1276634.28,100,427611.28,0.335
+earthquake,region_0,573536.74,481646.91,1055183.65,250,526759.95,0.499
+earthquake,region_1,629122.19,364783.94,993906.13,250,496953.07,0.5
+earthquake,region_2,746309.05,332187.9,1078496.95,250,539248.47,0.5
+earthquake,region_3,620072.81,268965.83,889038.64,250,411525.29,0.463
+earthquake,region_4,564022.92,287975.67,851998.59,250,395227.42,0.464
+earthquake,region_5,820437.37,295470.02,1115907.39,250,540731.59,0.485
+earthquake,region_6,948394.2,368490.41,1316884.62,250,658442.31,0.5
+earthquake,region_7,586159.94,298072.25,884232.19,250,401518.22,0.454
+earthquake,region_8,584467.53,319647.58,904115.12,250,422855.59,0.468
+earthquake,region_9,544351.27,280158.97,824510.23,250,409021.29,0.496
+earthquake,region_10,603166.86,341067.47,944234.32,250,472117.16,0.5
+earthquake,region_11,845197.41,259828.03,1105025.45,250,552512.72,0.5
+earthquake,region_12,813950.19,270439.76,1084389.95,250,542194.98,0.5
+earthquake,region_13,960436.2,265269.49,1225705.69,250,585504.61,0.478
+earthquake,region_14,903100.64,437064.92,1340165.56,250,627803.37,0.468
+earthquake,region_15,604674.66,342618.03,947292.69,250,472180.22,0.498
+earthquake,region_16,809127.39,342228.41,1151355.8,250,571364.31,0.496
+earthquake,region_17,873735.47,259170.8,1132906.27,250,538406.56,0.475
+earthquake,region_18,856674.79,473801.71,1330476.5,250,665238.25,0.5
+earthquake,region_19,766056.74,276793.0,1042849.75,250,515940.77,0.495
+earthquake,region_20,766308.63,310617.63,1076926.26,250,513612.33,0.477
+earthquake,region_21,688642.08,255017.8,943659.88,250,455040.27,0.482
+earthquake,region_22,605724.0,331874.34,937598.34,250,433148.13,0.462
+earthquake,region_23,945263.64,398398.11,1343661.75,250,671830.88,0.5
+earthquake,region_24,894585.62,374610.55,1269196.17,250,582170.17,0.459
+earthquake,region_25,768553.27,396710.28,1165263.55,250,582631.78,0.5
+earthquake,region_26,715829.77,281895.08,997724.85,250,477289.21,0.478
+earthquake,region_27,681541.15,411479.31,1093020.46,250,546510.23,0.5
+earthquake,region_28,678048.36,496628.81,1174677.18,250,587338.59,0.5
+earthquake,region_29,618613.4,275445.62,894059.01,250,415993.07,0.465
+earthquake,region_30,622978.86,290170.34,913149.21,250,427953.5,0.469
+earthquake,region_31,642547.58,293343.4,935890.98,250,467945.49,0.5
+earthquake,region_32,540116.87,381127.85,921244.72,250,452367.72,0.491
+earthquake,region_33,991189.31,278009.73,1269199.03,250,621635.36,0.49
+earthquake,region_34,984735.22,466376.78,1451112.0,250,725556.0,0.5
+earthquake,region_35,628951.41,292721.9,921673.31,250,460836.66,0.5
+earthquake,region_36,964687.99,389190.72,1353878.72,250,676939.36,0.5
+earthquake,region_37,639989.55,442373.23,1082362.78,250,507308.17,0.469
+earthquake,region_38,661839.62,356359.11,1018198.73,250,509099.36,0.5
+earthquake,region_39,621204.87,278709.21,899914.07,250,449957.04,0.5
+earthquake,region_40,644315.28,395309.56,1039624.83,250,483879.11,0.465
+earthquake,region_41,740570.05,383147.36,1123717.41,250,511496.34,0.455
+earthquake,region_42,668302.14,283603.67,951905.81,250,434390.31,0.456
+earthquake,region_43,994980.12,330588.46,1325568.58,250,662784.29,0.5
+earthquake,region_44,627320.33,420375.68,1047696.01,250,523848.0,0.5
+earthquake,region_45,797819.37,367894.05,1165713.42,250,572579.89,0.491
+earthquake,region_46,674434.13,482382.29,1156816.42,250,578408.21,0.5
+earthquake,region_47,982513.46,281074.31,1263587.76,250,631793.88,0.5
+earthquake,region_48,969170.23,295308.27,1264478.49,250,577423.63,0.457
+earthquake,region_49,870560.32,393618.28,1264178.6,250,632089.3,0.5
+earthquake,region_50,569886.19,448816.83,1018703.02,250,478956.19,0.47
+earthquake,region_51,581827.97,291066.45,872894.42,250,436447.21,0.5
+earthquake,region_52,832598.61,380766.36,1213364.97,250,589553.47,0.486
+earthquake,region_53,938600.27,348111.28,1286711.55,250,643355.77,0.5
+earthquake,region_54,719567.45,344236.11,1063803.56,250,527931.64,0.496
+earthquake,region_55,650688.94,436902.35,1087591.28,250,543795.64,0.5
+earthquake,region_56,616106.35,474893.64,1090999.99,250,532832.53,0.488
+earthquake,region_57,771776.43,476618.03,1248394.46,250,624197.23,0.5
+earthquake,region_58,558449.02,484958.03,1043407.05,250,521703.53,0.5
+earthquake,region_59,667452.81,284818.02,952270.83,250,476135.41,0.5
+earthquake,region_60,810036.38,383365.27,1193401.65,250,596700.83,0.5
+earthquake,region_61,894298.61,287918.72,1182217.33,250,568850.12,0.481
+earthquake,region_62,624244.57,435986.57,1060231.14,250,480659.23,0.453
+earthquake,region_63,784944.84,440614.67,1225559.51,250,612779.76,0.5
diff --git a/data/processed/asset_impacts/Example/flood.csv b/data/processed/asset_impacts/Example/flood.csv
new file mode 100644
index 0000000..9df72c5
--- /dev/null
+++ b/data/processed/asset_impacts/Example/flood.csv
@@ -0,0 +1,257 @@
+disaster_type,spatial_unit,residential,non_residential,total_exposed_stock,rp,pml,loss_fraction
+flood,region_0,687270.06,487678.58,1174948.64,10,97755.01,0.083
+flood,region_1,799329.24,289004.66,1088333.9,10,54416.7,0.05
+flood,region_2,529041.81,466544.04,995585.84,10,69802.02,0.07
+flood,region_3,854036.29,255146.12,1109182.41,10,118672.52,0.107
+flood,region_4,916221.32,303084.78,1219306.1,10,60965.3,0.05
+flood,region_5,591702.25,326060.56,917762.82,10,57337.82,0.062
+flood,region_6,715972.51,322807.29,1038779.79,10,73945.84,0.071
+flood,region_7,569746.93,323036.16,892783.09,10,44639.15,0.05
+flood,region_8,728034.99,446293.99,1174328.98,10,58716.45,0.05
+flood,region_9,757117.22,398103.64,1155220.86,10,57761.04,0.05
+flood,region_10,803772.43,292631.03,1096403.46,10,54820.17,0.05
+flood,region_11,974442.77,491408.01,1465850.78,10,133157.5,0.091
+flood,region_12,652306.88,274418.03,926724.91,10,72676.83,0.078
+flood,region_13,720076.25,280509.56,1000585.81,10,59552.56,0.06
+flood,region_14,517194.26,477330.1,994524.36,10,49726.22,0.05
+flood,region_15,831261.14,327927.77,1159188.91,10,71877.6,0.062
+flood,region_16,773355.14,296213.61,1069568.75,10,114399.43,0.107
+flood,region_17,887566.41,484874.74,1372441.15,10,136534.2,0.099
+flood,region_18,798949.99,480468.56,1279418.55,10,63970.93,0.05
+flood,region_19,597991.43,261306.82,859298.25,10,42964.91,0.05
+flood,region_20,694338.64,317837.26,1012175.9,10,94004.57,0.093
+flood,region_21,678376.66,320233.63,998610.29,10,64180.29,0.064
+flood,region_22,570462.11,450549.25,1021011.36,10,51050.57,0.05
+flood,region_23,993443.47,443061.19,1436504.66,10,71825.23,0.05
+flood,region_24,502761.06,453865.36,956626.42,10,77186.1,0.081
+flood,region_25,864503.58,442817.59,1307321.17,10,65366.06,0.05
+flood,region_26,679232.86,278967.26,958200.13,10,92284.58,0.096
+flood,region_27,811649.06,332724.51,1144373.57,10,57218.68,0.05
+flood,region_28,655491.16,331295.83,986786.99,10,81864.46,0.083
+flood,region_29,818778.74,471803.19,1290581.92,10,73849.02,0.057
+flood,region_30,559797.12,428311.2,988108.32,10,85054.89,0.086
+flood,region_31,780638.6,442741.79,1223380.39,10,72643.79,0.059
+flood,region_32,761366.41,356885.25,1118251.67,10,55912.58,0.05
+flood,region_33,553945.71,257857.3,811803.01,10,59782.02,0.074
+flood,region_34,657177.99,377142.67,1034320.66,10,104214.68,0.101
+flood,region_35,624646.11,352595.73,977241.85,10,83608.04,0.086
+flood,region_36,614399.08,269244.98,883644.06,10,44182.2,0.05
+flood,region_37,580610.64,482424.41,1063035.06,10,96536.38,0.091
+flood,region_38,816701.88,467865.15,1284567.03,10,116082.74,0.09
+flood,region_39,593285.03,473139.75,1066424.78,10,68181.04,0.064
+flood,region_40,903720.08,474022.82,1377742.9,10,68887.15,0.05
+flood,region_41,555025.96,306983.79,862009.75,10,45437.21,0.053
+flood,region_42,909007.38,465182.65,1374190.03,10,68709.5,0.05
+flood,region_43,755373.65,354352.75,1109726.4,10,55486.32,0.05
+flood,region_44,559932.68,334403.79,894336.48,10,93271.22,0.104
+flood,region_45,661601.47,379697.66,1041299.12,10,83618.29,0.08
+flood,region_46,681814.8,492945.52,1174760.32,10,124812.09,0.106
+flood,region_47,625891.15,374312.13,1000203.27,10,50010.16,0.05
+flood,region_48,642420.25,259221.74,901641.98,10,63977.3,0.071
+flood,region_49,751339.51,262869.69,1014209.2,10,50710.46,0.05
+flood,region_50,954132.94,309890.47,1264023.42,10,63201.17,0.05
+flood,region_51,744726.38,496412.61,1241138.99,10,62056.95,0.05
+flood,region_52,836067.77,440404.9,1276472.68,10,63823.63,0.05
+flood,region_53,864108.17,341945.78,1206053.96,10,88320.03,0.073
+flood,region_54,816764.86,383943.67,1200708.53,10,60035.43,0.05
+flood,region_55,917651.25,330195.02,1247846.26,10,62392.31,0.05
+flood,region_56,520387.57,397723.24,918110.81,10,71389.02,0.078
+flood,region_57,508293.91,378023.26,886317.18,10,44315.86,0.05
+flood,region_58,822586.4,293591.61,1116178.0,10,88282.73,0.079
+flood,region_59,693367.67,484182.5,1177550.17,10,58877.51,0.05
+flood,region_60,670533.18,278368.38,948901.56,10,97233.34,0.102
+flood,region_61,938669.68,314485.41,1253155.08,10,95237.79,0.076
+flood,region_62,908611.1,388800.2,1297411.3,10,81691.58,0.063
+flood,region_63,620926.15,273275.69,894201.84,10,89171.22,0.1
+flood,region_0,950209.03,408275.36,1358484.39,50,113980.89,0.084
+flood,region_1,674604.79,431488.92,1106093.71,50,154533.49,0.14
+flood,region_2,943543.21,444968.89,1388512.1,50,158572.48,0.114
+flood,region_3,542069.98,290407.18,832477.16,50,116426.44,0.14
+flood,region_4,803214.53,252299.26,1055513.79,50,63486.15,0.06
+flood,region_5,831750.88,251265.4,1083016.28,50,71566.59,0.066
+flood,region_6,774366.89,422973.8,1197340.69,50,137929.01,0.115
+flood,region_7,612134.65,428044.81,1040179.46,50,76687.14,0.074
+flood,region_8,662699.85,436622.85,1099322.7,50,126381.75,0.115
+flood,region_9,924611.71,414403.22,1339014.93,50,143048.12,0.107
+flood,region_10,546837.38,341928.95,888766.33,50,68008.61,0.077
+flood,region_11,621994.82,493252.64,1115247.46,50,99602.5,0.089
+flood,region_12,946023.28,407784.66,1353807.93,50,175292.58,0.129
+flood,region_13,751318.55,394225.97,1145544.52,50,113697.32,0.099
+flood,region_14,597621.49,430613.03,1028234.52,50,80281.71,0.078
+flood,region_15,512157.98,411368.07,923526.06,50,62532.94,0.068
+flood,region_16,970229.29,488482.14,1458711.44,50,206387.89,0.141
+flood,region_17,685079.35,253864.15,938943.5,50,134111.04,0.143
+flood,region_18,714092.07,491663.7,1205755.78,50,176476.82,0.146
+flood,region_19,926504.73,323612.22,1250116.95,50,110647.57,0.089
+flood,region_20,925568.34,329230.5,1254798.84,50,84007.87,0.067
+flood,region_21,778400.63,484038.69,1262439.32,50,150991.5,0.12
+flood,region_22,785030.59,274294.12,1059324.71,50,118115.47,0.112
+flood,region_23,995026.93,285021.0,1280047.93,50,130351.08,0.102
+flood,region_24,938686.54,435192.15,1373878.69,50,164455.44,0.12
+flood,region_25,851242.04,339872.79,1191114.83,50,94525.9,0.079
+flood,region_26,904680.58,452528.35,1357208.93,50,185540.28,0.137
+flood,region_27,956620.28,377835.6,1334455.88,50,133647.93,0.1
+flood,region_28,899147.59,412490.98,1311638.57,50,157654.61,0.12
+flood,region_29,897896.33,472501.34,1370397.67,50,114838.66,0.084
+flood,region_30,687791.48,273495.48,961286.96,50,103653.66,0.108
+flood,region_31,517971.14,366399.5,884370.64,50,92208.43,0.104
+flood,region_32,643270.63,397708.32,1040978.94,50,55223.96,0.053
+flood,region_33,518674.09,455650.14,974324.23,50,83810.46,0.086
+flood,region_34,563530.26,380560.82,944091.07,50,119898.96,0.127
+flood,region_35,607910.51,405722.62,1013633.13,50,59332.76,0.059
+flood,region_36,525840.86,382838.66,908679.52,50,94560.38,0.104
+flood,region_37,818714.95,431522.83,1250237.78,50,184516.6,0.148
+flood,region_38,758150.17,330739.12,1088889.29,50,141031.44,0.13
+flood,region_39,635416.13,359742.86,995158.98,50,57565.61,0.058
+flood,region_40,512675.37,490662.1,1003337.48,50,134043.89,0.134
+flood,region_41,847987.1,352238.24,1200225.34,50,80810.49,0.067
+flood,region_42,578218.52,312560.72,890779.25,50,93462.93,0.105
+flood,region_43,857297.96,415049.34,1272347.31,50,99234.68,0.078
+flood,region_44,977432.64,434474.23,1411906.87,50,148864.97,0.105
+flood,region_45,805860.37,354900.02,1160760.39,50,86793.65,0.075
+flood,region_46,677986.34,439461.53,1117447.87,50,57480.79,0.051
+flood,region_47,558036.32,261500.66,819536.98,50,44314.73,0.054
+flood,region_48,927730.29,425914.46,1353644.76,50,131868.53,0.097
+flood,region_49,548917.08,372903.97,921821.05,50,89736.68,0.097
+flood,region_50,586600.93,358462.91,945063.85,50,84914.43,0.09
+flood,region_51,807925.05,408773.41,1216698.46,50,66347.05,0.055
+flood,region_52,687306.31,406464.98,1093771.29,50,109720.16,0.1
+flood,region_53,928244.92,414673.41,1342918.33,50,89026.68,0.066
+flood,region_54,535284.37,410604.82,945889.19,50,49802.14,0.053
+flood,region_55,792887.79,485057.56,1277945.35,50,137439.72,0.108
+flood,region_56,694084.96,410822.05,1104907.02,50,105878.03,0.096
+flood,region_57,772808.39,485366.2,1258174.6,50,111487.18,0.089
+flood,region_58,980595.28,476337.66,1456932.94,50,101372.1,0.07
+flood,region_59,534680.65,275194.5,809875.15,50,41969.5,0.052
+flood,region_60,547221.48,420751.69,967973.17,50,55289.53,0.057
+flood,region_61,659487.82,461218.83,1120706.64,50,58643.43,0.052
+flood,region_62,907234.24,320463.69,1227697.93,50,75891.97,0.062
+flood,region_63,848368.58,407235.71,1255604.29,50,172955.98,0.138
+flood,region_0,867535.52,450870.23,1318405.75,100,169024.18,0.128
+flood,region_1,588719.77,437653.69,1026373.46,100,185448.72,0.181
+flood,region_2,995252.57,353154.42,1348406.99,100,185003.88,0.137
+flood,region_3,888206.48,335200.89,1223407.37,100,236210.27,0.193
+flood,region_4,929206.38,357248.51,1286454.88,100,225241.66,0.175
+flood,region_5,877271.44,275780.97,1153052.4,100,219374.32,0.19
+flood,region_6,752626.19,456614.37,1209240.55,100,159625.75,0.132
+flood,region_7,947761.61,347300.42,1295062.03,100,130909.75,0.101
+flood,region_8,952690.99,272821.67,1225512.66,100,161683.56,0.132
+flood,region_9,975030.98,487651.79,1462682.77,100,230144.05,0.157
+flood,region_10,815918.61,362111.38,1178029.99,100,152344.11,0.129
+flood,region_11,664332.27,418129.61,1082461.89,100,189687.86,0.175
+flood,region_12,895789.52,447404.54,1343194.06,100,146570.16,0.109
+flood,region_13,747210.15,264389.69,1011599.84,100,156750.32,0.155
+flood,region_14,720765.25,471926.05,1192691.3,100,161122.46,0.135
+flood,region_15,558533.51,285747.92,844281.43,100,148721.07,0.176
+flood,region_16,809109.03,275280.67,1084389.7,100,117559.43,0.108
+flood,region_17,850484.57,268190.75,1118675.32,100,203806.99,0.182
+flood,region_18,853121.11,270337.2,1123458.31,100,121876.99,0.108
+flood,region_19,993319.79,343567.7,1336887.49,100,183239.43,0.137
+flood,region_20,906399.78,486812.14,1393211.93,100,276692.04,0.199
+flood,region_21,876689.09,344064.9,1220753.99,100,132268.78,0.108
+flood,region_22,888573.46,389601.06,1278174.52,100,182040.43,0.142
+flood,region_23,953177.19,277799.37,1230976.56,100,183738.65,0.149
+flood,region_24,505676.82,367165.16,872841.98,100,92198.58,0.106
+flood,region_25,559408.96,279381.56,838790.52,100,138334.2,0.165
+flood,region_26,873022.44,395842.19,1268864.63,100,248973.13,0.196
+flood,region_27,687435.29,321428.02,1008863.31,100,188516.11,0.187
+flood,region_28,611797.92,490805.63,1102603.55,100,111600.51,0.101
+flood,region_29,984939.41,260789.98,1245729.39,100,235585.26,0.189
+flood,region_30,763850.55,498241.2,1262091.75,100,135522.98,0.107
+flood,region_31,776927.14,492325.63,1269252.78,100,193319.62,0.152
+flood,region_32,814699.32,423937.17,1238636.49,100,180164.76,0.145
+flood,region_33,813779.04,396078.58,1209857.62,100,230013.05,0.19
+flood,region_34,522723.19,320240.8,842963.99,100,164412.66,0.195
+flood,region_35,945131.89,363914.19,1309046.08,100,212082.82,0.162
+flood,region_36,638690.59,297030.29,935720.88,100,136961.32,0.146
+flood,region_37,676676.11,395914.03,1072590.14,100,115596.75,0.108
+flood,region_38,987197.4,496552.69,1483750.09,100,251964.76,0.17
+flood,region_39,768048.18,327381.9,1095430.09,100,198688.56,0.181
+flood,region_40,842365.59,290654.23,1133019.82,100,216511.84,0.191
+flood,region_41,911268.62,487449.98,1398718.6,100,241379.6,0.173
+flood,region_42,806707.6,354560.76,1161268.36,100,224441.64,0.193
+flood,region_43,933031.94,261304.67,1194336.61,100,122582.77,0.103
+flood,region_44,688231.68,452638.33,1140870.02,100,226722.37,0.199
+flood,region_45,575208.45,398532.68,973741.12,100,134463.02,0.138
+flood,region_46,984957.2,460529.73,1445486.93,100,265728.01,0.184
+flood,region_47,734346.58,353704.88,1088051.46,100,138553.24,0.127
+flood,region_48,528187.75,466180.59,994368.34,100,180269.14,0.181
+flood,region_49,999858.84,499159.21,1499018.05,100,233162.02,0.156
+flood,region_50,884493.71,486191.43,1370685.14,100,253528.42,0.185
+flood,region_51,623674.05,362636.03,986310.08,100,111370.13,0.113
+flood,region_52,977025.51,401543.66,1378569.17,100,169376.91,0.123
+flood,region_53,835850.34,404532.06,1240382.4,100,168464.11,0.136
+flood,region_54,556778.8,417893.3,974672.09,100,148180.15,0.152
+flood,region_55,886159.2,380040.88,1266200.07,100,234523.23,0.185
+flood,region_56,775953.42,390234.49,1166187.91,100,218853.07,0.188
+flood,region_57,701741.43,283503.81,985245.24,100,101360.32,0.103
+flood,region_58,877568.63,405077.39,1282646.02,100,218573.11,0.17
+flood,region_59,606482.08,284092.87,890574.95,100,90352.81,0.101
+flood,region_60,675293.78,397479.42,1072773.2,100,149356.21,0.139
+flood,region_61,718737.46,476039.67,1194777.13,100,161086.48,0.135
+flood,region_62,756994.74,445913.25,1202908.0,100,167991.25,0.14
+flood,region_63,811043.35,465590.93,1276634.28,100,248882.49,0.195
+flood,region_0,573536.74,481646.91,1055183.65,250,315723.22,0.299
+flood,region_1,629122.19,364783.94,993906.13,250,298171.84,0.3
+flood,region_2,746309.05,332187.9,1078496.95,250,323549.08,0.3
+flood,region_3,620072.81,268965.83,889038.64,250,233717.57,0.263
+flood,region_4,564022.92,287975.67,851998.59,250,224827.7,0.264
+flood,region_5,820437.37,295470.02,1115907.39,250,317550.12,0.285
+flood,region_6,948394.2,368490.41,1316884.62,250,395065.38,0.3
+flood,region_7,586159.94,298072.25,884232.19,250,224671.78,0.254
+flood,region_8,584467.53,319647.58,904115.12,250,242032.56,0.268
+flood,region_9,544351.27,280158.97,824510.23,250,244119.24,0.296
+flood,region_10,603166.86,341067.47,944234.32,250,283270.3,0.3
+flood,region_11,845197.41,259828.03,1105025.45,250,331507.63,0.3
+flood,region_12,813950.19,270439.76,1084389.95,250,325316.99,0.3
+flood,region_13,960436.2,265269.49,1225705.69,250,340363.47,0.278
+flood,region_14,903100.64,437064.92,1340165.56,250,359770.26,0.268
+flood,region_15,604674.66,342618.03,947292.69,250,282721.68,0.298
+flood,region_16,809127.39,342228.41,1151355.8,250,341093.15,0.296
+flood,region_17,873735.47,259170.8,1132906.27,250,311825.31,0.275
+flood,region_18,856674.79,473801.71,1330476.5,250,399142.95,0.3
+flood,region_19,766056.74,276793.0,1042849.75,250,307370.82,0.295
+flood,region_20,766308.63,310617.63,1076926.26,250,298227.08,0.277
+flood,region_21,688642.08,255017.8,943659.88,250,266308.29,0.282
+flood,region_22,605724.0,331874.34,937598.34,250,245628.46,0.262
+flood,region_23,945263.64,398398.11,1343661.75,250,403098.53,0.3
+flood,region_24,894585.62,374610.55,1269196.17,250,328330.93,0.259
+flood,region_25,768553.27,396710.28,1165263.55,250,349579.07,0.3
+flood,region_26,715829.77,281895.08,997724.85,250,277744.24,0.278
+flood,region_27,681541.15,411479.31,1093020.46,250,327906.14,0.3
+flood,region_28,678048.36,496628.81,1174677.18,250,352403.15,0.3
+flood,region_29,618613.4,275445.62,894059.01,250,237181.26,0.265
+flood,region_30,622978.86,290170.34,913149.21,250,245323.65,0.269
+flood,region_31,642547.58,293343.4,935890.98,250,280767.29,0.3
+flood,region_32,540116.87,381127.85,921244.72,250,268118.77,0.291
+flood,region_33,991189.31,278009.73,1269199.03,250,367795.55,0.29
+flood,region_34,984735.22,466376.78,1451112.0,250,435333.6,0.3
+flood,region_35,628951.41,292721.9,921673.31,250,276501.99,0.3
+flood,region_36,964687.99,389190.72,1353878.72,250,406163.62,0.3
+flood,region_37,639989.55,442373.23,1082362.78,250,290835.61,0.269
+flood,region_38,661839.62,356359.11,1018198.73,250,305459.62,0.3
+flood,region_39,621204.87,278709.21,899914.07,250,269974.22,0.3
+flood,region_40,644315.28,395309.56,1039624.83,250,275954.14,0.265
+flood,region_41,740570.05,383147.36,1123717.41,250,286752.85,0.255
+flood,region_42,668302.14,283603.67,951905.81,250,244009.15,0.256
+flood,region_43,994980.12,330588.46,1325568.58,250,397670.57,0.3
+flood,region_44,627320.33,420375.68,1047696.01,250,314308.8,0.3
+flood,region_45,797819.37,367894.05,1165713.42,250,339437.2,0.291
+flood,region_46,674434.13,482382.29,1156816.42,250,347044.93,0.3
+flood,region_47,982513.46,281074.31,1263587.76,250,379076.33,0.3
+flood,region_48,969170.23,295308.27,1264478.49,250,324527.93,0.257
+flood,region_49,870560.32,393618.28,1264178.6,250,379253.58,0.3
+flood,region_50,569886.19,448816.83,1018703.02,250,275215.59,0.27
+flood,region_51,581827.97,291066.45,872894.42,250,261868.33,0.3
+flood,region_52,832598.61,380766.36,1213364.97,250,346880.48,0.286
+flood,region_53,938600.27,348111.28,1286711.55,250,386013.46,0.3
+flood,region_54,719567.45,344236.11,1063803.56,250,315170.93,0.296
+flood,region_55,650688.94,436902.35,1087591.28,250,326277.38,0.3
+flood,region_56,616106.35,474893.64,1090999.99,250,314632.53,0.288
+flood,region_57,771776.43,476618.03,1248394.46,250,374518.34,0.3
+flood,region_58,558449.02,484958.03,1043407.05,250,313022.12,0.3
+flood,region_59,667452.81,284818.02,952270.83,250,285681.25,0.3
+flood,region_60,810036.38,383365.27,1193401.65,250,358020.5,0.3
+flood,region_61,894298.61,287918.72,1182217.33,250,332406.65,0.281
+flood,region_62,624244.57,435986.57,1060231.14,250,268613.0,0.253
+flood,region_63,784944.84,440614.67,1225559.51,250,367667.85,0.3
diff --git a/data/processed/asset_impacts/Example/hurricane.csv b/data/processed/asset_impacts/Example/hurricane.csv
new file mode 100644
index 0000000..b9cf43c
--- /dev/null
+++ b/data/processed/asset_impacts/Example/hurricane.csv
@@ -0,0 +1,257 @@
+disaster_type,spatial_unit,residential,non_residential,total_exposed_stock,rp,pml,loss_fraction
+hurricane,region_0,687270.06,487678.58,1174948.64,10,158852.34,0.135
+hurricane,region_1,799329.24,289004.66,1088333.9,10,108833.39,0.1
+hurricane,region_2,529041.81,466544.04,995585.84,10,121572.48,0.122
+hurricane,region_3,854036.29,255146.12,1109182.41,10,176350.0,0.159
+hurricane,region_4,916221.32,303084.78,1219306.1,10,121930.61,0.1
+hurricane,region_5,591702.25,326060.56,917762.82,10,105061.49,0.114
+hurricane,region_6,715972.51,322807.29,1038779.79,10,127962.39,0.123
+hurricane,region_7,569746.93,323036.16,892783.09,10,89278.31,0.1
+hurricane,region_8,728034.99,446293.99,1174328.98,10,117432.9,0.1
+hurricane,region_9,757117.22,398103.64,1155220.86,10,115522.09,0.1
+hurricane,region_10,803772.43,292631.03,1096403.46,10,109640.35,0.1
+hurricane,region_11,974442.77,491408.01,1465850.78,10,209381.74,0.143
+hurricane,region_12,652306.88,274418.03,926724.91,10,120866.52,0.13
+hurricane,region_13,720076.25,280509.56,1000585.81,10,111583.02,0.112
+hurricane,region_14,517194.26,477330.1,994524.36,10,99452.44,0.1
+hurricane,region_15,831261.14,327927.77,1159188.91,10,132155.42,0.114
+hurricane,region_16,773355.14,296213.61,1069568.75,10,170017.0,0.159
+hurricane,region_17,887566.41,484874.74,1372441.15,10,207901.14,0.151
+hurricane,region_18,798949.99,480468.56,1279418.55,10,127941.85,0.1
+hurricane,region_19,597991.43,261306.82,859298.25,10,85929.83,0.1
+hurricane,region_20,694338.64,317837.26,1012175.9,10,146637.72,0.145
+hurricane,region_21,678376.66,320233.63,998610.29,10,116108.03,0.116
+hurricane,region_22,570462.11,450549.25,1021011.36,10,102101.14,0.1
+hurricane,region_23,993443.47,443061.19,1436504.66,10,143650.47,0.1
+hurricane,region_24,502761.06,453865.36,956626.42,10,126930.68,0.133
+hurricane,region_25,864503.58,442817.59,1307321.17,10,130732.12,0.1
+hurricane,region_26,679232.86,278967.26,958200.13,10,142110.99,0.148
+hurricane,region_27,811649.06,332724.51,1144373.57,10,114437.36,0.1
+hurricane,region_28,655491.16,331295.83,986786.99,10,133177.38,0.135
+hurricane,region_29,818778.74,471803.19,1290581.92,10,140959.28,0.109
+hurricane,region_30,559797.12,428311.2,988108.32,10,136436.52,0.138
+hurricane,region_31,780638.6,442741.79,1223380.39,10,136259.57,0.111
+hurricane,region_32,761366.41,356885.25,1118251.67,10,111825.17,0.1
+hurricane,region_33,553945.71,257857.3,811803.01,10,101995.78,0.126
+hurricane,region_34,657177.99,377142.67,1034320.66,10,157999.36,0.153
+hurricane,region_35,624646.11,352595.73,977241.85,10,134424.61,0.138
+hurricane,region_36,614399.08,269244.98,883644.06,10,88364.41,0.1
+hurricane,region_37,580610.64,482424.41,1063035.06,10,151814.2,0.143
+hurricane,region_38,816701.88,467865.15,1284567.03,10,182880.22,0.142
+hurricane,region_39,593285.03,473139.75,1066424.78,10,123635.13,0.116
+hurricane,region_40,903720.08,474022.82,1377742.9,10,137774.29,0.1
+hurricane,region_41,555025.96,306983.79,862009.75,10,90261.71,0.105
+hurricane,region_42,909007.38,465182.65,1374190.03,10,137419.0,0.1
+hurricane,region_43,755373.65,354352.75,1109726.4,10,110972.64,0.1
+hurricane,region_44,559932.68,334403.79,894336.48,10,139776.72,0.156
+hurricane,region_45,661601.47,379697.66,1041299.12,10,137765.85,0.132
+hurricane,region_46,681814.8,492945.52,1174760.32,10,185899.63,0.158
+hurricane,region_47,625891.15,374312.13,1000203.27,10,100020.33,0.1
+hurricane,region_48,642420.25,259221.74,901641.98,10,110862.68,0.123
+hurricane,region_49,751339.51,262869.69,1014209.2,10,101420.92,0.1
+hurricane,region_50,954132.94,309890.47,1264023.42,10,126402.34,0.1
+hurricane,region_51,744726.38,496412.61,1241138.99,10,124113.9,0.1
+hurricane,region_52,836067.77,440404.9,1276472.68,10,127647.27,0.1
+hurricane,region_53,864108.17,341945.78,1206053.96,10,151034.84,0.125
+hurricane,region_54,816764.86,383943.67,1200708.53,10,120070.85,0.1
+hurricane,region_55,917651.25,330195.02,1247846.26,10,124784.63,0.1
+hurricane,region_56,520387.57,397723.24,918110.81,10,119130.79,0.13
+hurricane,region_57,508293.91,378023.26,886317.18,10,88631.72,0.1
+hurricane,region_58,822586.4,293591.61,1116178.0,10,146323.99,0.131
+hurricane,region_59,693367.67,484182.5,1177550.17,10,117755.02,0.1
+hurricane,region_60,670533.18,278368.38,948901.56,10,146576.22,0.154
+hurricane,region_61,938669.68,314485.41,1253155.08,10,160401.85,0.128
+hurricane,region_62,908611.1,388800.2,1297411.3,10,149156.97,0.115
+hurricane,region_63,620926.15,273275.69,894201.84,10,135669.71,0.152
+hurricane,region_0,950209.03,408275.36,1358484.39,50,195489.95,0.144
+hurricane,region_1,674604.79,431488.92,1106093.71,50,220899.11,0.2
+hurricane,region_2,943543.21,444968.89,1388512.1,50,241883.2,0.174
+hurricane,region_3,542069.98,290407.18,832477.16,50,166375.07,0.2
+hurricane,region_4,803214.53,252299.26,1055513.79,50,126816.98,0.12
+hurricane,region_5,831750.88,251265.4,1083016.28,50,136547.56,0.126
+hurricane,region_6,774366.89,422973.8,1197340.69,50,209769.45,0.175
+hurricane,region_7,612134.65,428044.81,1040179.46,50,139097.9,0.134
+hurricane,region_8,662699.85,436622.85,1099322.7,50,192341.12,0.175
+hurricane,region_9,924611.71,414403.22,1339014.93,50,223389.01,0.167
+hurricane,region_10,546837.38,341928.95,888766.33,50,121334.59,0.137
+hurricane,region_11,621994.82,493252.64,1115247.46,50,166517.34,0.149
+hurricane,region_12,946023.28,407784.66,1353807.93,50,256521.06,0.189
+hurricane,region_13,751318.55,394225.97,1145544.52,50,182429.99,0.159
+hurricane,region_14,597621.49,430613.03,1028234.52,50,141975.78,0.138
+hurricane,region_15,512157.98,411368.07,923526.06,50,117944.5,0.128
+hurricane,region_16,970229.29,488482.14,1458711.44,50,293910.57,0.201
+hurricane,region_17,685079.35,253864.15,938943.5,50,190447.65,0.203
+hurricane,region_18,714092.07,491663.7,1205755.78,50,248822.17,0.206
+hurricane,region_19,926504.73,323612.22,1250116.95,50,185654.58,0.149
+hurricane,region_20,925568.34,329230.5,1254798.84,50,159295.8,0.127
+hurricane,region_21,778400.63,484038.69,1262439.32,50,226737.86,0.18
+hurricane,region_22,785030.59,274294.12,1059324.71,50,181674.95,0.172
+hurricane,region_23,995026.93,285021.0,1280047.93,50,207153.95,0.162
+hurricane,region_24,938686.54,435192.15,1373878.69,50,246888.16,0.18
+hurricane,region_25,851242.04,339872.79,1191114.83,50,165992.79,0.139
+hurricane,region_26,904680.58,452528.35,1357208.93,50,266972.81,0.197
+hurricane,region_27,956620.28,377835.6,1334455.88,50,213715.28,0.16
+hurricane,region_28,899147.59,412490.98,1311638.57,50,236352.93,0.18
+hurricane,region_29,897896.33,472501.34,1370397.67,50,197062.52,0.144
+hurricane,region_30,687791.48,273495.48,961286.96,50,161330.88,0.168
+hurricane,region_31,517971.14,366399.5,884370.64,50,145270.67,0.164
+hurricane,region_32,643270.63,397708.32,1040978.94,50,117682.7,0.113
+hurricane,region_33,518674.09,455650.14,974324.23,50,142269.91,0.146
+hurricane,region_34,563530.26,380560.82,944091.07,50,176544.42,0.187
+hurricane,region_35,607910.51,405722.62,1013633.13,50,120150.75,0.119
+hurricane,region_36,525840.86,382838.66,908679.52,50,149081.15,0.164
+hurricane,region_37,818714.95,431522.83,1250237.78,50,259530.87,0.208
+hurricane,region_38,758150.17,330739.12,1088889.29,50,206364.8,0.19
+hurricane,region_39,635416.13,359742.86,995158.98,50,117275.15,0.118
+hurricane,region_40,512675.37,490662.1,1003337.48,50,194244.14,0.194
+hurricane,region_41,847987.1,352238.24,1200225.34,50,152824.01,0.127
+hurricane,region_42,578218.52,312560.72,890779.25,50,146909.69,0.165
+hurricane,region_43,857297.96,415049.34,1272347.31,50,175575.52,0.138
+hurricane,region_44,977432.64,434474.23,1411906.87,50,233579.39,0.165
+hurricane,region_45,805860.37,354900.02,1160760.39,50,156439.27,0.135
+hurricane,region_46,677986.34,439461.53,1117447.87,50,124527.66,0.111
+hurricane,region_47,558036.32,261500.66,819536.98,50,93486.94,0.114
+hurricane,region_48,927730.29,425914.46,1353644.76,50,213087.22,0.157
+hurricane,region_49,548917.08,372903.97,921821.05,50,145045.94,0.157
+hurricane,region_50,586600.93,358462.91,945063.85,50,141618.26,0.15
+hurricane,region_51,807925.05,408773.41,1216698.46,50,139348.96,0.115
+hurricane,region_52,687306.31,406464.98,1093771.29,50,175346.44,0.16
+hurricane,region_53,928244.92,414673.41,1342918.33,50,169601.78,0.126
+hurricane,region_54,535284.37,410604.82,945889.19,50,106555.49,0.113
+hurricane,region_55,792887.79,485057.56,1277945.35,50,214116.44,0.168
+hurricane,region_56,694084.96,410822.05,1104907.02,50,172172.46,0.156
+hurricane,region_57,772808.39,485366.2,1258174.6,50,186977.66,0.149
+hurricane,region_58,980595.28,476337.66,1456932.94,50,188788.08,0.13
+hurricane,region_59,534680.65,275194.5,809875.15,50,90562.01,0.112
+hurricane,region_60,547221.48,420751.69,967973.17,50,113367.92,0.117
+hurricane,region_61,659487.82,461218.83,1120706.64,50,125885.83,0.112
+hurricane,region_62,907234.24,320463.69,1227697.93,50,149553.84,0.122
+hurricane,region_63,848368.58,407235.71,1255604.29,50,248292.24,0.198
+hurricane,region_0,867535.52,450870.23,1318405.75,100,261312.58,0.198
+hurricane,region_1,588719.77,437653.69,1026373.46,100,257294.86,0.251
+hurricane,region_2,995252.57,353154.42,1348406.99,100,279392.37,0.207
+hurricane,region_3,888206.48,335200.89,1223407.37,100,321848.79,0.263
+hurricane,region_4,929206.38,357248.51,1286454.88,100,315293.51,0.245
+hurricane,region_5,877271.44,275780.97,1153052.4,100,300087.99,0.26
+hurricane,region_6,752626.19,456614.37,1209240.55,100,244272.59,0.202
+hurricane,region_7,947761.61,347300.42,1295062.03,100,221564.09,0.171
+hurricane,region_8,952690.99,272821.67,1225512.66,100,247469.44,0.202
+hurricane,region_9,975030.98,487651.79,1462682.77,100,332531.84,0.227
+hurricane,region_10,815918.61,362111.38,1178029.99,100,234806.21,0.199
+hurricane,region_11,664332.27,418129.61,1082461.89,100,265460.2,0.245
+hurricane,region_12,895789.52,447404.54,1343194.06,100,240593.74,0.179
+hurricane,region_13,747210.15,264389.69,1011599.84,100,227562.31,0.225
+hurricane,region_14,720765.25,471926.05,1192691.3,100,244610.85,0.205
+hurricane,region_15,558533.51,285747.92,844281.43,100,207820.77,0.246
+hurricane,region_16,809109.03,275280.67,1084389.7,100,193466.7,0.178
+hurricane,region_17,850484.57,268190.75,1118675.32,100,282114.26,0.252
+hurricane,region_18,853121.11,270337.2,1123458.31,100,200519.08,0.178
+hurricane,region_19,993319.79,343567.7,1336887.49,100,276821.56,0.207
+hurricane,region_20,906399.78,486812.14,1393211.93,100,374216.87,0.269
+hurricane,region_21,876689.09,344064.9,1220753.99,100,217721.56,0.178
+hurricane,region_22,888573.46,389601.06,1278174.52,100,271512.64,0.212
+hurricane,region_23,953177.19,277799.37,1230976.56,100,269907.01,0.219
+hurricane,region_24,505676.82,367165.16,872841.98,100,153297.52,0.176
+hurricane,region_25,559408.96,279381.56,838790.52,100,197049.53,0.235
+hurricane,region_26,873022.44,395842.19,1268864.63,100,337793.66,0.266
+hurricane,region_27,687435.29,321428.02,1008863.31,100,259136.54,0.257
+hurricane,region_28,611797.92,490805.63,1102603.55,100,188782.76,0.171
+hurricane,region_29,984939.41,260789.98,1245729.39,100,322786.31,0.259
+hurricane,region_30,763850.55,498241.2,1262091.75,100,223869.4,0.177
+hurricane,region_31,776927.14,492325.63,1269252.78,100,282167.31,0.222
+hurricane,region_32,814699.32,423937.17,1238636.49,100,266869.32,0.215
+hurricane,region_33,813779.04,396078.58,1209857.62,100,314703.08,0.26
+hurricane,region_34,522723.19,320240.8,842963.99,100,223420.14,0.265
+hurricane,region_35,945131.89,363914.19,1309046.08,100,303716.05,0.232
+hurricane,region_36,638690.59,297030.29,935720.88,100,202461.78,0.216
+hurricane,region_37,676676.11,395914.03,1072590.14,100,190678.06,0.178
+hurricane,region_38,987197.4,496552.69,1483750.09,100,355827.27,0.24
+hurricane,region_39,768048.18,327381.9,1095430.09,100,275368.67,0.251
+hurricane,region_40,842365.59,290654.23,1133019.82,100,295823.23,0.261
+hurricane,region_41,911268.62,487449.98,1398718.6,100,339289.9,0.243
+hurricane,region_42,806707.6,354560.76,1161268.36,100,305730.43,0.263
+hurricane,region_43,933031.94,261304.67,1194336.61,100,206186.33,0.173
+hurricane,region_44,688231.68,452638.33,1140870.02,100,306583.28,0.269
+hurricane,region_45,575208.45,398532.68,973741.12,100,202624.9,0.208
+hurricane,region_46,984957.2,460529.73,1445486.93,100,366912.1,0.254
+hurricane,region_47,734346.58,353704.88,1088051.46,100,214716.84,0.197
+hurricane,region_48,528187.75,466180.59,994368.34,100,249874.92,0.251
+hurricane,region_49,999858.84,499159.21,1499018.05,100,338093.28,0.226
+hurricane,region_50,884493.71,486191.43,1370685.14,100,349476.38,0.255
+hurricane,region_51,623674.05,362636.03,986310.08,100,180411.84,0.183
+hurricane,region_52,977025.51,401543.66,1378569.17,100,265876.75,0.193
+hurricane,region_53,835850.34,404532.06,1240382.4,100,255290.88,0.206
+hurricane,region_54,556778.8,417893.3,974672.09,100,216407.2,0.222
+hurricane,region_55,886159.2,380040.88,1266200.07,100,323157.24,0.255
+hurricane,region_56,775953.42,390234.49,1166187.91,100,300486.23,0.258
+hurricane,region_57,701741.43,283503.81,985245.24,100,170327.49,0.173
+hurricane,region_58,877568.63,405077.39,1282646.02,100,308358.33,0.24
+hurricane,region_59,606482.08,284092.87,890574.95,100,152693.05,0.171
+hurricane,region_60,675293.78,397479.42,1072773.2,100,224450.33,0.209
+hurricane,region_61,718737.46,476039.67,1194777.13,100,244720.88,0.205
+hurricane,region_62,756994.74,445913.25,1202908.0,100,252194.81,0.21
+hurricane,region_63,811043.35,465590.93,1276634.28,100,338246.88,0.265
+hurricane,region_0,573536.74,481646.91,1055183.65,250,421241.58,0.399
+hurricane,region_1,629122.19,364783.94,993906.13,250,397562.45,0.4
+hurricane,region_2,746309.05,332187.9,1078496.95,250,431398.78,0.4
+hurricane,region_3,620072.81,268965.83,889038.64,250,322621.43,0.363
+hurricane,region_4,564022.92,287975.67,851998.59,250,310027.56,0.364
+hurricane,region_5,820437.37,295470.02,1115907.39,250,429140.86,0.385
+hurricane,region_6,948394.2,368490.41,1316884.62,250,526753.85,0.4
+hurricane,region_7,586159.94,298072.25,884232.19,250,313095.0,0.354
+hurricane,region_8,584467.53,319647.58,904115.12,250,332444.08,0.368
+hurricane,region_9,544351.27,280158.97,824510.23,250,326570.26,0.396
+hurricane,region_10,603166.86,341067.47,944234.32,250,377693.73,0.4
+hurricane,region_11,845197.41,259828.03,1105025.45,250,442010.18,0.4
+hurricane,region_12,813950.19,270439.76,1084389.95,250,433755.98,0.4
+hurricane,region_13,960436.2,265269.49,1225705.69,250,462934.04,0.378
+hurricane,region_14,903100.64,437064.92,1340165.56,250,493786.82,0.368
+hurricane,region_15,604674.66,342618.03,947292.69,250,377450.95,0.398
+hurricane,region_16,809127.39,342228.41,1151355.8,250,456228.73,0.396
+hurricane,region_17,873735.47,259170.8,1132906.27,250,425115.93,0.375
+hurricane,region_18,856674.79,473801.71,1330476.5,250,532190.6,0.4
+hurricane,region_19,766056.74,276793.0,1042849.75,250,411655.8,0.395
+hurricane,region_20,766308.63,310617.63,1076926.26,250,405919.7,0.377
+hurricane,region_21,688642.08,255017.8,943659.88,250,360674.28,0.382
+hurricane,region_22,605724.0,331874.34,937598.34,250,339388.3,0.362
+hurricane,region_23,945263.64,398398.11,1343661.75,250,537464.7,0.4
+hurricane,region_24,894585.62,374610.55,1269196.17,250,455250.55,0.359
+hurricane,region_25,768553.27,396710.28,1165263.55,250,466105.42,0.4
+hurricane,region_26,715829.77,281895.08,997724.85,250,377516.72,0.378
+hurricane,region_27,681541.15,411479.31,1093020.46,250,437208.18,0.4
+hurricane,region_28,678048.36,496628.81,1174677.18,250,469870.87,0.4
+hurricane,region_29,618613.4,275445.62,894059.01,250,326587.16,0.365
+hurricane,region_30,622978.86,290170.34,913149.21,250,336638.58,0.369
+hurricane,region_31,642547.58,293343.4,935890.98,250,374356.39,0.4
+hurricane,region_32,540116.87,381127.85,921244.72,250,360243.24,0.391
+hurricane,region_33,991189.31,278009.73,1269199.03,250,494715.46,0.39
+hurricane,region_34,984735.22,466376.78,1451112.0,250,580444.8,0.4
+hurricane,region_35,628951.41,292721.9,921673.31,250,368669.32,0.4
+hurricane,region_36,964687.99,389190.72,1353878.72,250,541551.49,0.4
+hurricane,region_37,639989.55,442373.23,1082362.78,250,399071.89,0.369
+hurricane,region_38,661839.62,356359.11,1018198.73,250,407279.49,0.4
+hurricane,region_39,621204.87,278709.21,899914.07,250,359965.63,0.4
+hurricane,region_40,644315.28,395309.56,1039624.83,250,379916.62,0.365
+hurricane,region_41,740570.05,383147.36,1123717.41,250,399124.59,0.355
+hurricane,region_42,668302.14,283603.67,951905.81,250,339199.73,0.356
+hurricane,region_43,994980.12,330588.46,1325568.58,250,530227.43,0.4
+hurricane,region_44,627320.33,420375.68,1047696.01,250,419078.4,0.4
+hurricane,region_45,797819.37,367894.05,1165713.42,250,456008.54,0.391
+hurricane,region_46,674434.13,482382.29,1156816.42,250,462726.57,0.4
+hurricane,region_47,982513.46,281074.31,1263587.76,250,505435.1,0.4
+hurricane,region_48,969170.23,295308.27,1264478.49,250,450975.78,0.357
+hurricane,region_49,870560.32,393618.28,1264178.6,250,505671.44,0.4
+hurricane,region_50,569886.19,448816.83,1018703.02,250,377085.89,0.37
+hurricane,region_51,581827.97,291066.45,872894.42,250,349157.77,0.4
+hurricane,region_52,832598.61,380766.36,1213364.97,250,468216.97,0.386
+hurricane,region_53,938600.27,348111.28,1286711.55,250,514684.62,0.4
+hurricane,region_54,719567.45,344236.11,1063803.56,250,421551.29,0.396
+hurricane,region_55,650688.94,436902.35,1087591.28,250,435036.51,0.4
+hurricane,region_56,616106.35,474893.64,1090999.99,250,423732.53,0.388
+hurricane,region_57,771776.43,476618.03,1248394.46,250,499357.78,0.4
+hurricane,region_58,558449.02,484958.03,1043407.05,250,417362.82,0.4
+hurricane,region_59,667452.81,284818.02,952270.83,250,380908.33,0.4
+hurricane,region_60,810036.38,383365.27,1193401.65,250,477360.66,0.4
+hurricane,region_61,894298.61,287918.72,1182217.33,250,450628.39,0.381
+hurricane,region_62,624244.57,435986.57,1060231.14,250,374636.11,0.353
+hurricane,region_63,784944.84,440614.67,1225559.51,250,490223.81,0.4
diff --git a/data/processed/household_survey/Example.csv b/data/processed/household_survey/Example.csv
new file mode 100644
index 0000000..5b25ac8
--- /dev/null
+++ b/data/processed/household_survey/Example.csv
@@ -0,0 +1,101 @@
+spatial_unit,household_id,household_weight,inc,exp,sav,owns_home,exp_house,keff,roof,walls,floor,poverty_line,is_poor,female_headed,urban,literacy
+region_46,1,92.35290441231118,2882.026172983832,2401.688477486527,480.33769549730505,True,0.0,8234.360494239521,Shingle (wood),Plywood,Rudimentary – Wood planks,1571.281989361122,False,False,True,High
+region_55,2,30.113589575933442,2200.078604183612,1833.3988368196765,366.6797673639353,True,0.0,6285.938869096034,Shingle (other),Concrete/Concrete Blocks,Finished – Parquet or polished wood,1571.281989361122,False,False,False,Medium
+region_37,3,45.856330299438966,2489.3689920528695,2074.474160044058,414.8948320088116,True,0.0,7112.482834436771,Shingle (asphalt),Concrete/Concrete Blocks,Finished – Parquet or polished wood,1571.281989361122,False,True,False,High
+region_63,4,49.90182556473513,3000.0,2500.0,500.0,True,0.0,8571.428571428572,"Sheet metal (galvanize, galvalume)",Wood/Timber,Finished – Parquet or polished wood,1571.281989361122,False,False,True,High
+region_1,5,78.03898794957516,2933.778995074984,2444.815829229153,488.96316584583064,True,0.0,8382.22570021424,"Sheet metal (galvanize, galvalume)",Finished – Cement blocks,Finished – Cement/red bricks,1571.281989361122,False,False,False,High
+region_5,6,84.57926119374939,1511.3610600617944,1259.4675500514954,251.893510010299,True,0.0,4318.174457319413,Finished – Metal,Natural – Other,Finished – Cement/red bricks,1571.281989361122,True,False,False,Low
+region_6,7,14.768197413712668,2475.044208762795,2062.5368406356624,412.5073681271324,True,0.0,7071.554882179414,Concrete,Concrete/Concrete Blocks,Finished – Cement/red bricks,1571.281989361122,False,False,True,High
+region_12,8,43.2635316608963,1924.321395851151,1250.8089073032481,96.21606979255762,False,577.2964187553453,5498.061131003289,Finished – Concrete,Wood & Concrete,Finished – Cement/red bricks,1571.281989361122,False,False,True,Medium
+region_26,9,84.44263389571026,1948.390574103221,1623.6588117526842,324.7317623505369,True,0.0,5566.830211723489,Concrete,Finished – Cement blocks,Finished – Cement/red bricks,1571.281989361122,False,True,False,Medium
+region_10,10,81.98529726982801,2205.2992509691862,1837.7493758076553,367.54987516153096,True,0.0,6300.8550027691035,Finished – Metal,Concrete/Concrete blocks,Rudimentary – Wood planks,1571.281989361122,False,False,True,High
+region_59,11,11.138962086789224,2072.021785580439,1346.8141606272852,103.60108927902206,False,621.6065356741317,5920.06224451554,Concrete,Finished – Stone with lime/cement,Finished – Cement/red bricks,1571.281989361122,False,False,True,Medium
+region_54,12,16.48195153792834,2727.1367534814876,2272.6139612345733,454.5227922469144,True,0.0,7791.819295661393,Tile,Concrete/Concrete Blocks,Finished – Parquet or polished wood,1571.281989361122,False,False,True,High
+region_14,13,31.115670468341374,2380.518862573497,1983.7657188112473,396.75314376224946,True,0.0,6801.482464495705,Finished – Concrete,Concrete/Concrete blocks,Finished – Parquet or polished wood,1571.281989361122,False,False,True,High
+region_62,14,8.460547839250694,2060.837508246414,1717.3645902053452,343.47291804106885,True,0.0,5888.1071664183255,Shingle (wood),Concrete/Concrete blocks,Finished – Parquet or polished wood,1571.281989361122,False,False,True,Medium
+region_8,15,43.0416372812187,2221.9316163727126,1851.6096803105938,370.32193606211877,True,0.0,6348.376046779179,"Sheet metal (galvanize, galvalume)",Concrete/Concrete blocks,Other,1571.281989361122,False,False,True,High
+region_7,16,11.65415280980861,2166.8371636871334,1805.6976364059446,361.13952728118875,True,0.0,6190.963324820381,Tile,Natural – Other,Finished – Cement/red bricks,1571.281989361122,False,False,False,Medium
+region_45,17,57.25354177331466,2747.039536578803,2289.199613815669,457.8399227631339,True,0.0,7848.684390225152,Finished – Concrete,Finished – Stone with lime/cement,Rudimentary – Wood planks,1571.281989361122,False,False,False,High
+region_5,18,25.409137041304454,1897.4208681170996,1581.1840567642498,316.2368113528498,True,0.0,5421.20248033457,Tile,Natural – Other,Finished – Cement/red bricks,1571.281989361122,False,False,True,Medium
+region_47,19,60.04687346961265,2156.533850825451,1797.1115423545425,359.4223084709083,True,0.0,6161.525288072717,Shingle (wood),Finished – Stone with lime/cement,Finished – Parquet or polished wood,1571.281989361122,False,False,True,Medium
+region_59,20,12.635038647460128,1572.9521303491376,1310.7934419576147,262.1586883915229,True,0.0,4494.148943854679,Finished – Metal,Brick/Blocks,Finished – Cement/red bricks,1571.281989361122,False,False,True,Low
+region_42,21,97.6125029734348,1000.0,650.0,50.0,False,300.0,2857.1428571428573,Tile,Concrete/Concrete Blocks,Finished – Parquet or polished wood,1571.281989361122,True,False,False,Low
+region_3,22,93.3235591818767,2326.8092977201804,1939.0077481001504,387.8015496200301,True,0.0,6648.026564914801,Finished – Concrete,Rudimentary – Plywood,Finished – Cement/red bricks,1571.281989361122,False,False,True,High
+region_10,23,39.78789691790191,2432.218099429753,2026.8484161914607,405.36968323829205,True,0.0,6949.194569799294,Finished – Metal,Finished – Cement blocks,Finished – Cement/red bricks,1571.281989361122,False,True,True,High
+region_50,24,24.97568081848246,1628.9174897967791,1357.431241497316,271.4862482994631,True,0.0,4654.04997084794,Finished – Metal,Brick/Blocks,Finished – Cement/red bricks,1571.281989361122,False,False,True,Low
+region_57,25,25.789423072503705,3000.0,2500.0,500.0,True,0.0,8571.428571428572,Finished – Concrete,Finished – Cement blocks,Finished – Parquet or polished wood,1571.281989361122,False,False,True,High
+region_27,26,48.85595998503681,1272.8171627006177,827.3311557554016,63.64085813503078,False,381.8451488101853,3636.620464858908,Finished – Metal,Rudimentary – Plywood,Rudimentary – Wood planks,1571.281989361122,True,False,False,Low
+region_25,27,4.95928738817098,2022.879258650723,1685.7327155422693,337.14654310845367,True,0.0,5779.655024716351,Finished – Concrete,Concrete/Concrete Blocks,Finished – Cement/red bricks,1571.281989361122,False,True,True,Medium
+region_3,28,64.33080550143757,1906.4080749870832,1588.6733958225693,317.73467916451386,True,0.0,5446.880214248809,Finished – Concrete,Finished – Cement blocks,Finished – Cement/red bricks,1571.281989361122,False,False,False,Medium
+region_61,29,41.42198792563474,2766.3896071792287,2305.3246726493576,461.06493452987115,True,0.0,7903.970306226368,Tile,Finished – Stone with lime/cement,Finished – Cement/red bricks,1571.281989361122,False,False,False,High
+region_14,30,38.36325068629984,2734.679384950143,2278.8994874584523,455.77989749169046,True,0.0,7813.369671286122,Shingle (other),Concrete/Concrete blocks,Finished – Cement/red bricks,1571.281989361122,False,False,False,High
+region_18,31,81.12713217743064,2077.473712848458,1731.2280940403818,346.2456188080762,True,0.0,5935.639179567023,Finished – Concrete,Wood & Concrete,Finished – Cement/red bricks,1571.281989361122,False,True,False,Medium
+region_5,32,71.19451055814571,2189.0812598010866,1824.2343831675723,364.8468766335143,True,0.0,6254.517885145962,Shingle (wood),Brick/Blocks,Finished – Cement/red bricks,1571.281989361122,False,False,True,Medium
+region_58,33,95.4790477238765,1556.1071261849436,1296.755938487453,259.35118769749056,True,0.0,4446.0203605284105,Finished – Asbestos,Concrete/Concrete Blocks,Finished – Cement/red bricks,1571.281989361122,True,False,False,Low
+region_4,34,35.841687809073385,1009.6017658880365,841.3348049066972,168.26696098133937,True,0.0,2884.576473965819,Concrete,Concrete/Concrete Blocks,Finished – Cement/red bricks,1571.281989361122,True,False,False,Low
+region_17,35,89.85673370029114,1826.0439253369236,1521.703271114103,304.3406542228206,True,0.0,5217.268358105496,Finished – Concrete,Brick/Blocks,Finished – Cement/red bricks,1571.281989361122,False,False,False,Medium
+region_5,36,77.2267514387588,2078.17448455199,1350.8134149587936,103.90872422759958,False,623.452345365597,5937.641384434258,Finished – Metal,Finished – Cement blocks,Rudimentary – Wood planks,1571.281989361122,False,True,True,Medium
+region_63,37,36.38504050787659,2615.14534036386,2179.28778363655,435.8575567273101,True,0.0,7471.843829611029,Concrete,Brick/Blocks,Finished – Cement/red bricks,1571.281989361122,False,False,True,High
+region_30,38,62.54487820887252,2601.1899243922057,1690.7734508549333,130.05949621961065,False,780.3569773176617,7431.97121254916,Finished – Concrete,Finished – Cement blocks,Finished – Parquet or polished wood,1571.281989361122,False,False,True,High
+region_24,39,29.568425807517862,1806.336591296024,1505.2804927466866,301.0560985493373,True,0.0,5160.961689417211,Shingle (other),Plywood,Rudimentary – Wood planks,1571.281989361122,False,False,True,Low
+region_3,40,87.56559179040939,1848.8486247123321,1540.707187260277,308.14143745205524,True,0.0,5282.424642035235,Shingle (asphalt),Concrete/Concrete blocks,Finished – Parquet or polished wood,1571.281989361122,False,False,False,Medium
+region_5,41,12.130304404018814,1475.7235174664538,959.220286353195,73.78617587332269,False,442.71705523993614,4216.352907047011,Tile,Concrete/Concrete blocks,Finished – Cement/red bricks,1571.281989361122,True,False,False,Low
+region_40,42,22.031001768110062,1289.9910314105123,1074.992526175427,214.9985052350853,True,0.0,3685.6886611728924,Shingle (asphalt),Finished – Cement blocks,Finished – Cement/red bricks,1571.281989361122,True,False,False,Low
+region_36,43,19.120295915912195,1146.8649046874937,745.4621880468708,57.34324523437482,False,344.05947140624806,3276.756870535696,Finished – Concrete,Wood & Concrete,Finished – Cement/red bricks,1571.281989361122,True,True,False,Low
+region_58,44,40.89957423802458,2975.387697615895,2479.489748013246,495.8979496026491,True,0.0,8501.107707473986,Finished – Concrete,Wood & Concrete,Finished – Parquet or polished wood,1571.281989361122,False,False,True,High
+region_49,45,74.77806304318078,1745.1739091241732,1134.3630409307125,87.25869545620878,False,523.5521727372519,4986.211168926209,Shingle (asphalt),Finished – Cement blocks,Finished – Cement/red bricks,1571.281989361122,False,False,True,Low
+region_55,46,53.16383745616585,1780.9628491944068,1157.6258519763644,89.04814245972034,False,534.288854758322,5088.465283412591,Finished – Asbestos,Rudimentary – Plywood,Rudimentary – Wood planks,1571.281989361122,False,True,False,Low
+region_24,47,49.27995603028255,1373.602319975037,892.841507983774,68.68011599875194,False,412.0806959925111,3924.5780570715347,Tile,Finished – Cement blocks,Rudimentary – Wood planks,1571.281989361122,True,False,False,Low
+region_33,48,1.0540505248025698,2388.745177915955,1990.6209815966292,398.12419631932585,True,0.0,6824.986222617014,Finished – Concrete,Finished – Stone with lime/cement,Other,1571.281989361122,False,True,False,High
+region_18,49,43.11477081015042,1193.0510762210242,775.4831995436657,59.65255381105129,False,357.91532286630724,3408.7173606314977,Concrete,Wood & Concrete,Finished – Cement/red bricks,1571.281989361122,True,True,False,Low
+region_33,50,7.291823708779685,1893.6298598930157,1578.0248832441798,315.6049766488359,True,0.0,5410.371028265759,Shingle (asphalt),Finished – GRC/Gypsum/Asbestos,Rudimentary – Wood planks,1571.281989361122,False,True,False,Medium
+region_14,51,21.617071960026898,1552.2667194031621,1293.5555995026352,258.7111199005269,True,0.0,4435.047769723321,Concrete,Rudimentary – Plywood,Finished – Cement/red bricks,1571.281989361122,True,False,True,Low
+region_49,52,93.30699995708895,2193.451248929631,1827.8760407746927,365.57520815493854,True,0.0,6267.003568370375,Finished – Concrete,Wood/Timber,Rudimentary – Wood planks,1571.281989361122,False,False,False,Medium
+region_7,53,22.32442222998058,1744.5974312155636,1133.9883302901162,87.22987156077829,False,523.3792293646691,4984.5640891873245,Tile,Finished – GRC/Gypsum/Asbestos,Finished – Parquet or polished wood,1571.281989361122,False,False,False,Low
+region_53,54,85.97542622479199,1409.683907938794,916.2945401602159,70.48419539693987,False,422.9051723816382,4027.668308396554,Shingle (wood),Finished – Stone with lime/cement,Other,1571.281989361122,True,False,False,Low
+region_43,55,80.48644378457209,1985.9088858306725,1654.9240715255605,330.98481430511197,True,0.0,5674.025388087636,Concrete,Finished – Cement blocks,Rudimentary – Wood planks,1571.281989361122,False,False,False,Medium
+region_46,56,16.75547745728204,2214.1659352652086,1845.138279387674,369.0276558775347,True,0.0,6326.188386472025,Finished – Metal,Concrete/Concrete blocks,Finished – Cement/red bricks,1571.281989361122,False,True,False,High
+region_48,57,60.965483769757604,2033.258611191584,1321.6180972745294,101.66293055957931,False,609.9775833574752,5809.31031769024,Concrete,Concrete/Concrete blocks,Finished – Parquet or polished wood,1571.281989361122,False,True,True,Medium
+region_52,58,12.450525318596318,2151.2359488698908,1792.6966240582424,358.5393248116484,True,0.0,6146.388425342545,Finished – Concrete,Concrete/Concrete Blocks,Finished – Cement/red bricks,1571.281989361122,False,False,False,Medium
+region_63,59,73.06092767858163,1682.8389531595183,1093.8453195536867,84.14194765797606,False,504.85168594785546,4808.111294741481,Tile,Finished – Cement blocks,Finished – Cement/red bricks,1571.281989361122,False,False,False,Low
+region_33,60,64.10876545984846,1818.629417006431,1515.5245141720259,303.10490283440504,True,0.0,5196.0840485898025,Finished – Concrete,Brick/Blocks,Finished – Cement/red bricks,1571.281989361122,False,False,True,Medium
+region_17,61,81.38191760741091,1663.7697761120244,1081.450354472816,83.1884888056012,False,499.1309328336073,4753.6279317486415,Finished – Concrete,Finished – GRC/Gypsum/Asbestos,Finished – Parquet or polished wood,1571.281989361122,False,False,True,Low
+region_29,62,48.45907038952962,1820.2234192297294,1183.145222499324,91.01117096148653,False,546.0670257689188,5200.63834065637,Concrete,Plywood,Finished – Parquet or polished wood,1571.281989361122,False,False,True,Medium
+region_12,63,91.5714456955049,1593.426858977773,1035.7274583355525,79.67134294888865,False,478.0280576933319,4552.648168507923,Tile,Concrete/Concrete blocks,Finished – Cement/red bricks,1571.281989361122,False,False,False,Low
+region_54,64,5.885545732055531,1136.8586988341617,947.3822490284681,189.47644980569362,True,0.0,3248.1677109547477,Shingle (asphalt),Concrete/Concrete blocks,Finished – Parquet or polished wood,1571.281989361122,True,False,False,Low
+region_46,65,29.99596793767445,2088.7130711268765,1740.5942259390638,348.11884518781267,True,0.0,5967.751631791076,Shingle (asphalt),Wood & Concrete,Finished – Cement/red bricks,1571.281989361122,False,False,True,Medium
+region_54,66,71.79020714905154,1799.1095318958692,1499.2579432465577,299.85158864931145,True,0.0,5140.312948273912,Shingle (wood),Finished – Stone with lime/cement,Finished – Cement/red bricks,1571.281989361122,False,False,False,Low
+region_32,67,42.39281196305208,1184.9008265169778,987.4173554308148,197.48347108616292,True,0.0,3385.430932905651,Concrete,Wood/Timber,Finished – Cement/red bricks,1571.281989361122,True,False,False,Low
+region_34,68,18.12218407284448,2231.391127762887,1859.4926064690728,371.8985212938144,True,0.0,6375.403222179678,Shingle (asphalt),Natural – Other,Other,1571.281989361122,False,False,True,High
+region_51,69,11.613863797426056,1546.350817808379,1288.6256815069826,257.72513630139633,True,0.0,4418.145193738225,Tile,Rudimentary – Plywood,Finished – Cement/red bricks,1571.281989361122,True,True,False,Low
+region_23,70,81.91657203470052,2025.9726978980696,1316.882253633745,101.29863489490367,False,607.7918093694209,5788.4934225659135,Tile,Finished – Cement blocks,Finished – Cement/red bricks,1571.281989361122,False,False,True,Medium
+region_60,71,47.841154868098776,2364.545281088768,1970.454400907307,394.0908801814612,True,0.0,6755.843660253624,"Sheet metal (galvanize, galvalume)",Finished – Cement blocks,Finished – Parquet or polished wood,1571.281989361122,False,False,True,High
+region_25,72,88.34608351999164,2064.4914553787053,1341.9194459961584,103.22457276893533,False,619.3474366136115,5898.54701536773,Concrete,Concrete/Concrete blocks,Finished – Cement/red bricks,1571.281989361122,False,False,True,Medium
+region_46,73,73.59562429735588,2569.7003422716502,2141.416951893042,428.28339037860815,True,0.0,7342.000977919,Shingle (asphalt),Finished – Stone with lime/cement,Rudimentary – Wood planks,1571.281989361122,False,False,True,High
+region_50,74,41.56289435744361,1382.5870898231738,1152.1559081859782,230.43118163719555,True,0.0,3950.248828066211,Shingle (other),Wood & Concrete,Finished – Parquet or polished wood,1571.281989361122,True,True,False,Low
+region_43,75,37.977590401412684,2201.1708205887744,1834.3090171573122,366.86180343146225,True,0.0,6289.059487396498,Finished – Metal,Wood/Timber,Other,1571.281989361122,False,True,False,High
+region_52,76,52.04819631847392,1657.5949545298433,1381.3291287748696,276.2658257549738,True,0.0,4735.985584370981,Finished – Concrete,Concrete/Concrete blocks,Finished – Parquet or polished wood,1571.281989361122,False,False,False,Low
+region_41,77,89.01693536578314,1564.6014254090592,1303.834521174216,260.7669042348432,True,0.0,4470.289786883026,Shingle (other),Brick/Blocks,Finished – Cement/red bricks,1571.281989361122,True,False,False,Low
+region_46,78,73.99057939170262,1710.5751676177922,1111.873858951565,85.52875838088971,False,513.1725502853376,4887.357621765121,Concrete,Wood & Concrete,Finished – Parquet or polished wood,1571.281989361122,False,False,False,Low
+region_0,79,1.5101434626333,1844.2237339363137,1536.8531116135948,307.3706223227189,True,0.0,5269.210668389468,Finished – Metal,Concrete/Concrete Blocks,Other,1571.281989361122,False,False,True,Medium
+region_12,80,69.72162728554343,2028.0826711148727,1318.2537362246671,101.40413355574378,False,608.4248013344618,5794.521917471065,Finished – Metal,Concrete/Concrete Blocks,Finished – Parquet or polished wood,1571.281989361122,False,True,True,Medium
+region_54,81,92.03123328367624,1417.4250796083218,921.326301745409,70.87125398041627,False,425.22752388249654,4049.7859417380623,Shingle (asphalt),Wood/Timber,Finished – Cement/red bricks,1571.281989361122,True,True,False,Low
+region_9,82,71.33512019094466,2450.4132434770936,2042.0110362309115,408.4022072461821,True,0.0,7001.180695648839,Concrete,Concrete/Concrete blocks,Rudimentary – Wood planks,1571.281989361122,False,True,True,High
+region_18,83,18.523572375182095,2232.8312198652297,1860.692683221025,372.1385366442048,True,0.0,6379.517771043514,Finished – Concrete,Brick/Blocks,Finished – Cement/red bricks,1571.281989361122,False,False,True,High
+region_4,84,48.86829461531841,1231.878156861388,1026.5651307178234,205.31302614356468,True,0.0,3519.6518767468233,Finished – Metal,Concrete/Concrete blocks,Finished – Cement/red bricks,1571.281989361122,True,False,True,Low
+region_7,85,14.891285774418522,2744.1260968978,2286.7717474148335,457.3543494829664,True,0.0,7840.360276850857,Shingle (asphalt),Brick/Blocks,Finished – Cement/red bricks,1571.281989361122,False,False,False,High
+region_3,86,36.54053255562358,2947.9445880152916,2456.620490012743,491.32409800254845,True,0.0,8422.698822900833,Shingle (wood),Rudimentary – Plywood,Finished – Cement/red bricks,1571.281989361122,False,False,True,High
+region_48,87,93.77458715211125,2589.3897855798255,2157.824821316521,431.5649642633043,True,0.0,7398.256530228073,Tile,Finished – Cement blocks,Rudimentary – Wood planks,1571.281989361122,False,False,False,High
+region_12,88,92.40722544831212,1910.0375820938245,1591.6979850781872,318.3395970156373,True,0.0,5457.250234553784,Concrete,Wood/Timber,Finished – Parquet or polished wood,1571.281989361122,False,False,True,Medium
+region_37,89,29.00084836543221,1464.6236892447287,1220.519741037274,244.10394820745478,True,0.0,4184.639112127797,"Sheet metal (galvanize, galvalume)",Concrete/Concrete blocks,Finished – Cement/red bricks,1571.281989361122,True,False,True,Low
+region_52,90,34.62347337245372,2527.225863465568,2106.0215528879735,421.2043105775947,True,0.0,7220.645324187338,Finished – Asbestos,Concrete/Concrete Blocks,Finished – Cement/red bricks,1571.281989361122,False,False,True,High
+region_45,91,60.4210739449981,1798.41152651341,1498.6762720945085,299.7352544189016,True,0.0,5138.318647181171,Finished – Metal,Finished – Cement blocks,Rudimentary – Wood planks,1571.281989361122,False,True,False,Low
+region_48,92,96.35653223077762,2611.222535191214,2176.0187793260116,435.2037558652023,True,0.0,7460.63581483204,Shingle (wood),Finished – Cement blocks,Other,1571.281989361122,False,False,True,High
+region_45,93,15.632332072473652,2104.13748903843,1753.447907532025,350.6895815064049,True,0.0,6011.821397252657,Tile,Finished – Stone with lime/cement,Other,1571.281989361122,False,False,True,Medium
+region_18,94,26.43474772498024,2488.3195182418563,2073.5995985348804,414.7199197069758,True,0.0,7109.4843378338755,Shingle (wood),Finished – Cement blocks,Finished – Cement/red bricks,1571.281989361122,False,False,True,High
+region_51,95,87.48212590178638,2178.183198587201,1815.1526654893341,363.03053309786674,True,0.0,6223.380567392002,Finished – Asbestos,Finished – Stone with lime/cement,Other,1571.281989361122,False,False,False,Medium
+region_49,96,49.697330939126104,2353.286584095974,1961.0721534133118,392.21443068266217,True,0.0,6723.675954559925,"Sheet metal (galvanize, galvalume)",Wood & Concrete,Rudimentary – Wood planks,1571.281989361122,False,False,False,High
+region_7,97,89.99714813047613,2005.2500103604102,1303.4125067342666,100.2625005180206,False,601.575003108123,5729.285743886887,Shingle (wood),Finished – Cement blocks,Finished – Parquet or polished wood,1571.281989361122,False,False,True,Medium
+region_26,98,19.36627185479445,2892.9352469529176,1880.4079105193964,144.6467623476459,False,867.8805740858753,8265.529277008336,Concrete,Finished – Cement blocks,Finished – Cement/red bricks,1571.281989361122,False,False,True,High
+region_49,99,53.734190159664706,2063.45604635181,1719.5467052931751,343.90934105863494,True,0.0,5895.588703862315,Concrete,Wood & Concrete,Finished – Cement/red bricks,1571.281989361122,False,False,True,Medium
+region_46,100,33.30069363228787,2200.994681722351,1834.1622347686257,366.83244695372514,True,0.0,6288.556233492431,Finished – Concrete,Concrete/Concrete blocks,Finished – Cement/red bricks,1571.281989361122,False,False,True,Medium
diff --git a/docs/index.html b/docs/index.html
deleted file mode 100644
index 0ef869b..0000000
--- a/docs/index.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/docs/search.js b/docs/search.js
deleted file mode 100644
index c969eea..0000000
--- a/docs/search.js
+++ /dev/null
@@ -1,46 +0,0 @@
-window.pdocSearch = (function(){
-/** elasticlunr - http://weixsong.github.io * Copyright (C) 2017 Oliver Nightingale * Copyright (C) 2017 Wei Song * MIT Licensed */!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();o
\n"}, "src.data": {"fullname": "src.data", "modulename": "src.data", "kind": "module", "doc": "
\n"}, "src.data.analyse": {"fullname": "src.data.analyse", "modulename": "src.data.analyse", "kind": "module", "doc": "
\n"}, "src.data.analyse.prepare_outcomes": {"fullname": "src.data.analyse.prepare_outcomes", "modulename": "src.data.analyse", "qualname": "prepare_outcomes", "kind": "function", "doc": "Convert outcomes dict into a data frame.
\n\nArgs:\n results (tuple): The results of the experiments in the EMA Workbench format.\n add_policies (bool): Whether to add policy values to the data frame.\n add_uncertainties (bool): Whether to add uncertainty values to the data frame.
\n\nReturns:\n pd.DataFrame: Outcomes data frame.
\n", "signature": "(\tresults : tuple , \tadd_policies : bool , \tadd_uncertainties : bool ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.analyse.get_spatial_outcomes": {"fullname": "src.data.analyse.get_spatial_outcomes", "modulename": "src.data.analyse", "qualname": "get_spatial_outcomes", "kind": "function", "doc": "
\n", "signature": "(\toutcomes : pandas . core . frame . DataFrame , \toutcomes_of_interest : list = [] , \tcountry : str = 'Saint Lucia' , \taggregation : str = 'mean' ) -> geopandas . geodataframe . GeoDataFrame : ", "funcdef": "def"}, "src.data.analyse.get_policy_effectiveness_tab": {"fullname": "src.data.analyse.get_policy_effectiveness_tab", "modulename": "src.data.analyse", "qualname": "get_policy_effectiveness_tab", "kind": "function", "doc": "
\n", "signature": "(outcomes : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare": {"fullname": "src.data.prepare", "modulename": "src.data.prepare", "kind": "module", "doc": "
\n"}, "src.data.prepare.prepare_asset_damage": {"fullname": "src.data.prepare.prepare_asset_damage", "modulename": "src.data.prepare", "qualname": "prepare_asset_damage", "kind": "function", "doc": "Prepare district-level asset damage data and save it into a XLSX file.
\n", "signature": "(country : str , scale : str , return_period : int = 100 ) -> None : ", "funcdef": "def"}, "src.data.prepare.prepare_household_survey": {"fullname": "src.data.prepare.prepare_household_survey", "modulename": "src.data.prepare", "qualname": "prepare_household_survey", "kind": "function", "doc": "Prepare data for the simulation model.
\n\nParameters \n\ncountry : str
\n\nRaises \n\nValueError\n If the country is not supported.
\n", "signature": "(country : str ) -> None : ", "funcdef": "def"}, "src.data.prepare.load_data": {"fullname": "src.data.prepare.load_data", "modulename": "src.data.prepare", "qualname": "load_data", "kind": "function", "doc": "Load the raw data.
\n", "signature": "(print_statistics : bool = True ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.start_pipeline": {"fullname": "src.data.prepare.start_pipeline", "modulename": "src.data.prepare", "qualname": "start_pipeline", "kind": "function", "doc": "Start the data processing pipeline.
\n", "signature": "(data : pandas . core . frame . DataFrame ): ", "funcdef": "def"}, "src.data.prepare.add_is_rural_column": {"fullname": "src.data.prepare.add_is_rural_column", "modulename": "src.data.prepare", "qualname": "add_is_rural_column", "kind": "function", "doc": "Create a new column that indicates whether the household is rural or not.
\n", "signature": "(\tdata : pandas . core . frame . DataFrame , \tprint_statistics : bool = True ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.rename_assets_column": {"fullname": "src.data.prepare.rename_assets_column", "modulename": "src.data.prepare", "qualname": "rename_assets_column", "kind": "function", "doc": "Rename the assets column to be more descriptive.
\n", "signature": "(data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.rename_other_columns": {"fullname": "src.data.prepare.rename_other_columns", "modulename": "src.data.prepare", "qualname": "rename_other_columns", "kind": "function", "doc": "Rename a set of columns. See function for details.
\n", "signature": "(data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.calculate_household_attributes": {"fullname": "src.data.prepare.calculate_household_attributes", "modulename": "src.data.prepare", "qualname": "calculate_household_attributes", "kind": "function", "doc": "
\n", "signature": "(data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.get_bank_or_credit_union": {"fullname": "src.data.prepare.get_bank_or_credit_union", "modulename": "src.data.prepare", "qualname": "get_bank_or_credit_union", "kind": "function", "doc": "
\n", "signature": "(data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.decode_demographic_attributes": {"fullname": "src.data.prepare.decode_demographic_attributes", "modulename": "src.data.prepare", "qualname": "decode_demographic_attributes", "kind": "function", "doc": "Decode the demographic attributes.
\n", "signature": "(data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.decode_income_attributes": {"fullname": "src.data.prepare.decode_income_attributes", "modulename": "src.data.prepare", "qualname": "decode_income_attributes", "kind": "function", "doc": "Decode the income-related attributes.
\n", "signature": "(data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.calculate_income_attributes": {"fullname": "src.data.prepare.calculate_income_attributes", "modulename": "src.data.prepare", "qualname": "calculate_income_attributes", "kind": "function", "doc": "
\n", "signature": "(data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.decode_housing_attributes": {"fullname": "src.data.prepare.decode_housing_attributes", "modulename": "src.data.prepare", "qualname": "decode_housing_attributes", "kind": "function", "doc": "Decode the housing-related attributes.
\n", "signature": "(data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.add_housing_attributes": {"fullname": "src.data.prepare.add_housing_attributes", "modulename": "src.data.prepare", "qualname": "add_housing_attributes", "kind": "function", "doc": "Introduce new housing attributes.
\n", "signature": "(data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.add_insurance_attributes": {"fullname": "src.data.prepare.add_insurance_attributes", "modulename": "src.data.prepare", "qualname": "add_insurance_attributes", "kind": "function", "doc": "
\n", "signature": "(data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.calculate_housing_attributes": {"fullname": "src.data.prepare.calculate_housing_attributes", "modulename": "src.data.prepare", "qualname": "calculate_housing_attributes", "kind": "function", "doc": "
\n", "signature": "(data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.calculate_poverty_attributes": {"fullname": "src.data.prepare.calculate_poverty_attributes", "modulename": "src.data.prepare", "qualname": "calculate_poverty_attributes", "kind": "function", "doc": "
\n", "signature": "(data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.assign_housing_vulnerability": {"fullname": "src.data.prepare.assign_housing_vulnerability", "modulename": "src.data.prepare", "qualname": "assign_housing_vulnerability", "kind": "function", "doc": "
\n", "signature": "(data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.subset_columns": {"fullname": "src.data.prepare.subset_columns", "modulename": "src.data.prepare", "qualname": "subset_columns", "kind": "function", "doc": "Subset columns of interest.
\n", "signature": "(data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.check_columns": {"fullname": "src.data.prepare.check_columns", "modulename": "src.data.prepare", "qualname": "check_columns", "kind": "function", "doc": "
\n", "signature": "(data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.add_missing_columns": {"fullname": "src.data.prepare.add_missing_columns", "modulename": "src.data.prepare", "qualname": "add_missing_columns", "kind": "function", "doc": "Manually add missing columns to the data.
\n", "signature": "(\tdata : pandas . core . frame . DataFrame , \tmissing_columns : list ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.merge_districts": {"fullname": "src.data.prepare.merge_districts", "modulename": "src.data.prepare", "qualname": "merge_districts", "kind": "function", "doc": "
\n", "signature": "(data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.prepare.exponential_regression": {"fullname": "src.data.prepare.exponential_regression", "modulename": "src.data.prepare", "qualname": "exponential_regression", "kind": "function", "doc": "
\n", "signature": "(\tdata : pandas . core . frame . DataFrame , \tX_column : str , \ty_column : str , \tweights : < built - in function array > = None , \treturn_model : bool = False ) -> tuple [ numpy . array , float ] : ", "funcdef": "def"}, "src.data.prepare.polynomial_regression": {"fullname": "src.data.prepare.polynomial_regression", "modulename": "src.data.prepare", "qualname": "polynomial_regression", "kind": "function", "doc": "
\n", "signature": "(\tdata : pandas . core . frame . DataFrame , \tX_column : str , \ty_column : str , \tpower : int , \tweights : < built - in function array > = None , \tX_new : < built - in function array > = None , \tX_start : int = 0 , \tX_end : int = 40 , \tX_num : int = 100 ): ", "funcdef": "def"}, "src.data.prepare.linear_regression": {"fullname": "src.data.prepare.linear_regression", "modulename": "src.data.prepare", "qualname": "linear_regression", "kind": "function", "doc": "Do a linear regression on the data and return the predicted values, the coefficient and the r2 score.
\n", "signature": "(\tdata : pandas . core . frame . DataFrame , \tX_column : str , \ty_column : str , \tweights : < built - in function array > = None , \treturn_model : bool = False ) -> tuple [ numpy . array , float , float ] : ", "funcdef": "def"}, "src.data.read": {"fullname": "src.data.read", "modulename": "src.data.read", "kind": "module", "doc": "
\n"}, "src.data.read.read_asset_damage": {"fullname": "src.data.read.read_asset_damage", "modulename": "src.data.read", "qualname": "read_asset_damage", "kind": "function", "doc": "Read asset damage for all districts from a XLSX file and load it into the memory.
\n", "signature": "(country ) -> None : ", "funcdef": "def"}, "src.data.read.get_asset_damage": {"fullname": "src.data.read.get_asset_damage", "modulename": "src.data.read", "qualname": "get_asset_damage", "kind": "function", "doc": "Get asset damage for a specific district.
\n\nArgs:\n all_damage (pd.DataFrame): Asset damage data for all districts.\n scale (str): Scale of the analysis. Only district
is supported.\n district (str): District name.\n return_period (int): Return period.\n print_statistics (bool): Print the statistics.
\n\nReturns:\n tuple: Event damage, total asset stock, expected loss fraction.
\n\nRaises:\n ValueError: If the scale is not district
. \n ValueError: If the expected loss fraction is greater than 1.
\n", "signature": "(\tall_damage : pandas . core . frame . DataFrame , \tscale : str , \tdistrict : str , \treturn_period : int , \tprint_statistics : bool ) -> tuple : ", "funcdef": "def"}, "src.data.read.read_household_survey": {"fullname": "src.data.read.read_household_survey", "modulename": "src.data.read", "qualname": "read_household_survey", "kind": "function", "doc": "Reads household survey from a CSV file.
\n\nArgs:\n country (str): Country name.
\n\nReturns:\n pd.DataFrame: Household survey data.
\n\nRaises:\n ValueError: If the country is not Saint Lucia
.
\n", "signature": "(country : str ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.visualise": {"fullname": "src.data.visualise", "modulename": "src.data.visualise", "kind": "module", "doc": "
\n"}, "src.data.visualise.rainclouds": {"fullname": "src.data.visualise.rainclouds", "modulename": "src.data.visualise", "qualname": "rainclouds", "kind": "function", "doc": "
\n", "signature": "(\toutcomes : pandas . core . frame . DataFrame , \tsavefigs : bool , \tx_columns : list = [] , \tx_titles : list = [] , \tplot_years_in_poverty : bool = False , \tcolor_palette : str = 'Set2' , \tsharex : bool = True ): ", "funcdef": "def"}, "src.data.visualise.bivariate_choropleth": {"fullname": "src.data.visualise.bivariate_choropleth", "modulename": "src.data.visualise", "qualname": "bivariate_choropleth", "kind": "function", "doc": "
\n", "signature": "(data , x_name , y_name , x_label , y_label , scale , figsize , return_table ): ", "funcdef": "def"}, "src.data.visualise.nine_quadrants_plot": {"fullname": "src.data.visualise.nine_quadrants_plot", "modulename": "src.data.visualise", "qualname": "nine_quadrants_plot", "kind": "function", "doc": "
\n", "signature": "(data , x_name , y_name , scale = True ): ", "funcdef": "def"}, "src.data.visualise.get_colors": {"fullname": "src.data.visualise.get_colors", "modulename": "src.data.visualise", "qualname": "get_colors", "kind": "function", "doc": "
\n", "signature": "(data ): ", "funcdef": "def"}, "src.data.visualise.bin_data": {"fullname": "src.data.visualise.bin_data", "modulename": "src.data.visualise", "qualname": "bin_data", "kind": "function", "doc": "
\n", "signature": "(data , x_name , y_name , scale , print_statistics = True ): ", "funcdef": "def"}, "src.data.write": {"fullname": "src.data.write", "modulename": "src.data.write", "kind": "module", "doc": "
\n"}, "src.data.write.add_columns": {"fullname": "src.data.write.add_columns", "modulename": "src.data.write", "qualname": "add_columns", "kind": "function", "doc": "Add columns/outcomes of interest from affected households
to the households
dataframe.
\n", "signature": "(\thouseholds : pandas . core . frame . DataFrame , \taffected_households : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.data.write.get_outcomes": {"fullname": "src.data.write.get_outcomes", "modulename": "src.data.write", "qualname": "get_outcomes", "kind": "function", "doc": "Calculate outcomes of interest from the simulation model.
\n\nArgs:\n households (pd.DataFrame): Households data frame.\n event_damage (float): Event damage.\n total_asset_stock (float): Total asset stock.\n expected_loss_fraction (float): Expected loss fraction.\n average_productivity (float): Average productivity.\n n_years (float): Number of years to consider for calculations (same as for optimization algorithm).
\n\nReturns:\n dict: Outcomes of interest.
\n", "signature": "(\thouseholds , \tevent_damage , \ttotal_asset_stock , \texpected_loss_fraction , \taverage_productivity , \tn_years ) -> dict : ", "funcdef": "def"}, "src.data.write.find_poor": {"fullname": "src.data.write.find_poor", "modulename": "src.data.write", "qualname": "find_poor", "kind": "function", "doc": "Get the poor at the beginning of the simulation and the poor at the end of the simulation
\n\nArgs:\n households (pd.DataFrame): Household dataframe\n poverty_line (float): Poverty line
\n\nReturns:\n tuple: Number of poor at the beginning of the simulation, number of new poor at the end of the simulation, and the new poor dataframe
\n", "signature": "(\thouseholds : pandas . core . frame . DataFrame , \tpoverty_line : float , \tn_years : int ) -> tuple : ", "funcdef": "def"}, "src.data.write.get_people_by_years_in_poverty": {"fullname": "src.data.write.get_people_by_years_in_poverty", "modulename": "src.data.write", "qualname": "get_people_by_years_in_poverty", "kind": "function", "doc": "Get the number of people in poverty for each year in poverty.
\n\nArgs:\n new_poor (pd.DataFrame): New poor dataframe
\n\nReturns:\n dict: Number of people in poverty for each year in poverty
\n", "signature": "(new_poor : pandas . core . frame . DataFrame ) -> dict : ", "funcdef": "def"}, "src.data.write.calculate_poverty_gap": {"fullname": "src.data.write.calculate_poverty_gap", "modulename": "src.data.write", "qualname": "calculate_poverty_gap", "kind": "function", "doc": "Calculate the poverty gap at the beginning and at the end of the simulation.
\n\nArgs:\n poor_initial (pd.DataFrame): Poor at the beginning of the simulation\n new_poor (pd.DataFrame): New poor at the end of the simulation\n poverty_line (float): Poverty line\n n_years (int): Number of years of the optimization algorithm
\n\nReturns:\n tuple: Poverty gap at the beginning and at the end of the simulation
\n\nRaises:\n Exception: If the index is duplicated\n Exception: If the poverty gap is greater than 1
\n", "signature": "(\tpoor_initial : pandas . core . frame . DataFrame , \tnew_poor : pandas . core . frame . DataFrame , \tpoverty_line : float , \tn_years : int ) -> tuple : ", "funcdef": "def"}, "src.data.write.calculate_average_annual_consumption_loss": {"fullname": "src.data.write.calculate_average_annual_consumption_loss", "modulename": "src.data.write", "qualname": "calculate_average_annual_consumption_loss", "kind": "function", "doc": "Get the average annual consumption loss and the average annual consumption loss as a percentage of average annual consumption.
\n\nArgs:\n affected_households (pd.DataFrame): Affected households dataframe\n n_years (int): Number of years of the optimization algorithm
\n\nReturns:\n tuple: Average annual consumption loss and average annual consumption loss as a percentage of average annual consumption
\n\nRaises:\n Exception: If the average annual consumption loss is greater than 1
\n", "signature": "(affected_households : pandas . core . frame . DataFrame , n_years : int ) -> tuple : ", "funcdef": "def"}, "src.data.write.calculate_resilience": {"fullname": "src.data.write.calculate_resilience", "modulename": "src.data.write", "qualname": "calculate_resilience", "kind": "function", "doc": "Calculate the resilience of the affected households.
\n\nArgs:\n affected_households (pd.DataFrame): Affected households dataframe\n pml (float): Probable maximum loss
\n\nReturns:\n tuple: Resilience and number of times resilience is greater than 1
\n\nRaises:\n Exception: If the total consumption loss is 0
\n", "signature": "(affected_households : pandas . core . frame . DataFrame , pml : float ) -> tuple : ", "funcdef": "def"}, "src.model": {"fullname": "src.model", "modulename": "src.model", "kind": "module", "doc": "
\n"}, "src.model.initialize_model": {"fullname": "src.model.initialize_model", "modulename": "src.model", "qualname": "initialize_model", "kind": "function", "doc": "Initialize the model by reading household survey and asset damage files.
\n\nArgs:\n country (str): Country name.\n min_households (int): Minimum number of households that we need to have in a sample to be representative.
\n\nReturns:\n tuple: Household survey and asset damage files.
\n", "signature": "(country : str , min_households : int ) -> tuple : ", "funcdef": "def"}, "src.model.run_model": {"fullname": "src.model.run_model", "modulename": "src.model", "qualname": "run_model", "kind": "function", "doc": "Run the model.
\n", "signature": "(** kwargs ): ", "funcdef": "def"}, "src.modules": {"fullname": "src.modules", "modulename": "src.modules", "kind": "module", "doc": "
\n"}, "src.modules.households": {"fullname": "src.modules.households", "modulename": "src.modules.households", "kind": "module", "doc": "
\n"}, "src.modules.households.duplicate_households": {"fullname": "src.modules.households.duplicate_households", "modulename": "src.modules.households", "qualname": "duplicate_households", "kind": "function", "doc": "Duplicates households if the number of households is less than min_households
threshold.
\n\nArgs:\n household_survey (pd.DataFrame): Household survey data.\n min_households (int): Minimum number of households.
\n\nReturns:\n pd.DataFrame: Household survey data with duplicated households.
\n\nRaises:\n ValueError: If the total weights after duplication is not equal to the initial total weights.
\n", "signature": "(\thousehold_survey : pandas . core . frame . DataFrame , \tmin_households : int ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.modules.households.calculate_average_productivity": {"fullname": "src.modules.households.calculate_average_productivity", "modulename": "src.modules.households", "qualname": "calculate_average_productivity", "kind": "function", "doc": "Calculate average productivity as aeinc \\ k_house_ae.
\n\nArgs:\n households (pd.DataFrame): Household survey data.\n print_statistics (bool, optional): Whether to print the average productivity. Defaults to False.
\n\nReturns:\n float: Average productivity.
\n", "signature": "(households : pandas . core . frame . DataFrame , print_statistics : bool ) -> float : ", "funcdef": "def"}, "src.modules.households.adjust_assets_and_expenditure": {"fullname": "src.modules.households.adjust_assets_and_expenditure", "modulename": "src.modules.households", "qualname": "adjust_assets_and_expenditure", "kind": "function", "doc": "Adjust assets and expenditure of household to match data of asset damage file.
\n\nThere can be a mismatch between the data in the household survey and the of the asset damage.\nThe latest was created independently.
\n\nArgs:\n households (pd.DataFrame): Household survey data.\n total_asset_stock (float): Total asset stock.\n poverty_line (float): Poverty line.\n indigence_line (float): Indigence line.\n print_statistics (bool, optional): Whether to print the statistics. Defaults to False.
\n\nReturns:\n pd.DataFrame: Household survey data with adjusted assets and expenditure.
\n", "signature": "(\thouseholds : pandas . core . frame . DataFrame , \ttotal_asset_stock : float , \tpoverty_line : float , \tindigence_line : float , \tprint_statistics : bool ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.modules.households.calculate_pml": {"fullname": "src.modules.households.calculate_pml", "modulename": "src.modules.households", "qualname": "calculate_pml", "kind": "function", "doc": "Calculate probable maximum loss as a product of population weight, effective capital stock and expected loss fraction.
\n\nArgs:\n households (pd.DataFrame): Household survey data.\n expected_loss_fraction (float): Expected loss fraction.\n print_statistics (bool, optional): Whether to print the statistics. Defaults to False.
\n\nReturns:\n pd.DataFrame: Household survey data with probable maximum loss.
\n", "signature": "(\thouseholds : pandas . core . frame . DataFrame , \texpected_loss_fraction : float , \tprint_statistics : bool ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.modules.households.select_district": {"fullname": "src.modules.households.select_district", "modulename": "src.modules.households", "qualname": "select_district", "kind": "function", "doc": "Select households for a specific district.
\n", "signature": "(\thousehold_survey : pandas . core . frame . DataFrame , \tdistrict : str ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.modules.households.estimate_savings": {"fullname": "src.modules.households.estimate_savings", "modulename": "src.modules.households", "qualname": "estimate_savings", "kind": "function", "doc": "Estimate savings of households.
\n\nWe assume that savings are a product of expenditure and saving rate with Gaussian noise.
\n\nArgs:\n households (pd.DataFrame): Household survey data for a specific district.\n saving_rate (float): Saving rate.\n estimate_savings_params (dict): Parameters for estimating savings function.
\n\nReturns:\n pd.DataFrame: Household survey data with estimated savings.
\n", "signature": "(\thouseholds : pandas . core . frame . DataFrame , \tsaving_rate : float , \testimate_savings_params : dict ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.modules.households.set_vulnerability": {"fullname": "src.modules.households.set_vulnerability", "modulename": "src.modules.households", "qualname": "set_vulnerability", "kind": "function", "doc": "Set vulnerability of households.
\n\nVulnerability can be random or based on v_init
with uniform noise.
\n\nArgs:\n households (pd.DataFrame): Household survey data for a specific district.\n is_vulnerability_random (bool): If True, vulnerability is random.
\n\nReturns:\n pd.DataFrame: Household survey data with assigned vulnerability.
\n\nRaises:\n ValueError: If the distribution is not supported.
\n", "signature": "(\thouseholds : pandas . core . frame . DataFrame , \tis_vulnerability_random : bool , \tset_vulnerability_params : dict ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.modules.households.calculate_exposure": {"fullname": "src.modules.households.calculate_exposure", "modulename": "src.modules.households", "qualname": "calculate_exposure", "kind": "function", "doc": "Calculate exposure of households.
\n\nExposure is a function of poverty bias, effective capital stock, \nvulnerability and probable maximum loss.
\n\nArgs:\n households (pd.DataFrame): Household survey data for a specific district.\n poverty_bias (float): Poverty bias.\n calculate_exposure_params (dict): Parameters for calculating exposure function.\n print_statistics (bool): If True, print statistics.
\n\nReturns:\n pd.DataFrame: Household survey data with calculated exposure.
\n", "signature": "(\thouseholds : pandas . core . frame . DataFrame , \tpoverty_bias : float , \tcalculate_exposure_params : dict , \tprint_statistics : bool ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.modules.households.determine_affected": {"fullname": "src.modules.households.determine_affected", "modulename": "src.modules.households", "qualname": "determine_affected", "kind": "function", "doc": "Determines affected households.
\n\nWe assume that all households have the same probability of being affected, \nbut based on fa
calculated in calculate_exposure
.
\n\nArgs:\n households (pd.DataFrame): Household survey data for a specific district.\n determine_affected_params (dict): Parameters for determining affected households function.
\n\nReturns:\n tuple: Household survey data with determined affected households and asset loss for each household.
\n\nRaises:\n ValueError: If total asset is less than PML.\n ValueError: If no mask was found.
\n", "signature": "(\thouseholds : pandas . core . frame . DataFrame , \tdetermine_affected_params : dict ) -> tuple : ", "funcdef": "def"}, "src.modules.households.apply_individual_policy": {"fullname": "src.modules.households.apply_individual_policy", "modulename": "src.modules.households", "qualname": "apply_individual_policy", "kind": "function", "doc": "Apply a policy to a specific target group.
\n\nArgs:\n households (pd.DataFrame): Household survey data for a specific district.\n my_policy (str): Policy to apply. The structure of the policy is target_group
+top_up
in a single string. target_group
can be all
, poor
, poor_near_poor1.25
, poor_near_poor2.0
, and the top_up
0, 10, 30 or 50.
\n\nReturns:\n tuple: Household survey data with applied policy and affected households.
\n", "signature": "(households : pandas . core . frame . DataFrame , my_policy : str ) -> tuple : ", "funcdef": "def"}, "src.modules.optimize": {"fullname": "src.modules.optimize", "modulename": "src.modules.optimize", "kind": "module", "doc": "
\n"}, "src.modules.optimize.run_optimization": {"fullname": "src.modules.optimize.run_optimization", "modulename": "src.modules.optimize", "qualname": "run_optimization", "kind": "function", "doc": "This function calculates the recovery rate for each affected household.
\n\nArgs:\n affected_households (pd.DataFrame): A data frame containing the affected households.\n consumption_utility (float): The coefficient of relative risk aversion.\n discount_rate (float): The discount rate.\n average_productivity (float): The average productivity.\n optimization_timestep (float): The timestep for the optimization.\n n_years (int): The number of years in the optimization algorithm.
\n\nReturns:\n pd.DataFrame: A data frame containing the affected households with the recovery rate.
\n", "signature": "(\taffected_households : pandas . core . frame . DataFrame , \tconsumption_utility : float , \tdiscount_rate : float , \taverage_productivity : float , \toptimization_timestep : float , \tn_years : int ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}, "src.modules.optimize.optimize_recovery_rate": {"fullname": "src.modules.optimize.optimize_recovery_rate", "modulename": "src.modules.optimize", "qualname": "optimize_recovery_rate", "kind": "function", "doc": "
\n", "signature": "(\tx , \toptimization_results : pandas . core . frame . DataFrame , \tconsumption_utility : float , \tdiscount_rate : float , \taverage_productivity : float , \toptimization_timestep : float , \tn_years : int ) -> float : ", "funcdef": "def"}, "src.modules.optimize.integrate_wellbeing": {"fullname": "src.modules.optimize.integrate_wellbeing", "modulename": "src.modules.optimize", "qualname": "integrate_wellbeing", "kind": "function", "doc": "
\n", "signature": "(\taffected_households : pandas . core . frame . DataFrame , \tconsumption_utility : float , \tdiscount_rate : float , \tincome_and_expenditure_growth : float , \taverage_productivity : float , \tpoverty_line : float , \tn_years : int , \tadd_income_loss : bool , \tcash_transfer : dict = {} ) -> pandas . core . frame . DataFrame : ", "funcdef": "def"}}, "docInfo": {"src": {"qualname": 0, "fullname": 1, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "src.data": {"qualname": 0, "fullname": 2, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "src.data.analyse": {"qualname": 0, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "src.data.analyse.prepare_outcomes": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 59, "bases": 0, "doc": 62}, "src.data.analyse.get_spatial_outcomes": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 110, "bases": 0, "doc": 3}, "src.data.analyse.get_policy_effectiveness_tab": {"qualname": 4, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 3}, "src.data.prepare": {"qualname": 0, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "src.data.prepare.prepare_asset_damage": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 47, "bases": 0, "doc": 16}, "src.data.prepare.prepare_household_survey": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 19, "bases": 0, "doc": 30}, "src.data.prepare.load_data": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 42, "bases": 0, "doc": 7}, "src.data.prepare.start_pipeline": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 31, "bases": 0, "doc": 8}, "src.data.prepare.add_is_rural_column": {"qualname": 4, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 69, "bases": 0, "doc": 16}, "src.data.prepare.rename_assets_column": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 11}, "src.data.prepare.rename_other_columns": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 12}, "src.data.prepare.calculate_household_attributes": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 3}, "src.data.prepare.get_bank_or_credit_union": {"qualname": 5, "fullname": 8, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 3}, "src.data.prepare.decode_demographic_attributes": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 7}, "src.data.prepare.decode_income_attributes": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 8}, "src.data.prepare.calculate_income_attributes": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 3}, "src.data.prepare.decode_housing_attributes": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 8}, "src.data.prepare.add_housing_attributes": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 7}, "src.data.prepare.add_insurance_attributes": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 3}, "src.data.prepare.calculate_housing_attributes": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 3}, "src.data.prepare.calculate_poverty_attributes": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 3}, "src.data.prepare.assign_housing_vulnerability": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 3}, "src.data.prepare.subset_columns": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 7}, "src.data.prepare.check_columns": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 3}, "src.data.prepare.add_missing_columns": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 62, "bases": 0, "doc": 10}, "src.data.prepare.merge_districts": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 49, "bases": 0, "doc": 3}, "src.data.prepare.exponential_regression": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 132, "bases": 0, "doc": 3}, "src.data.prepare.polynomial_regression": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 199, "bases": 0, "doc": 3}, "src.data.prepare.linear_regression": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 138, "bases": 0, "doc": 21}, "src.data.read": {"qualname": 0, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "src.data.read.read_asset_damage": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 19}, "src.data.read.get_asset_damage": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 82, "bases": 0, "doc": 94}, "src.data.read.read_household_survey": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 34, "bases": 0, "doc": 42}, "src.data.visualise": {"qualname": 0, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "src.data.visualise.rainclouds": {"qualname": 1, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 143, "bases": 0, "doc": 3}, "src.data.visualise.bivariate_choropleth": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 51, "bases": 0, "doc": 3}, "src.data.visualise.nine_quadrants_plot": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 33, "bases": 0, "doc": 3}, "src.data.visualise.get_colors": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 3}, "src.data.visualise.bin_data": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 39, "bases": 0, "doc": 3}, "src.data.write": {"qualname": 0, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "src.data.write.add_columns": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 77, "bases": 0, "doc": 18}, "src.data.write.get_outcomes": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 52, "bases": 0, "doc": 74}, "src.data.write.find_poor": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 59, "bases": 0, "doc": 63}, "src.data.write.get_people_by_years_in_poverty": {"qualname": 6, "fullname": 9, "annotation": 0, "default_value": 0, "signature": 35, "bases": 0, "doc": 40}, "src.data.write.calculate_poverty_gap": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 87, "bases": 0, "doc": 96}, "src.data.write.calculate_average_annual_consumption_loss": {"qualname": 5, "fullname": 8, "annotation": 0, "default_value": 0, "signature": 46, "bases": 0, "doc": 78}, "src.data.write.calculate_resilience": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 45, "bases": 0, "doc": 52}, "src.model": {"qualname": 0, "fullname": 2, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "src.model.initialize_model": {"qualname": 2, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 30, "bases": 0, "doc": 53}, "src.model.run_model": {"qualname": 2, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 13, "bases": 0, "doc": 6}, "src.modules": {"qualname": 0, "fullname": 2, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "src.modules.households": {"qualname": 0, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "src.modules.households.duplicate_households": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 63, "bases": 0, "doc": 69}, "src.modules.households.calculate_average_productivity": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 45, "bases": 0, "doc": 44}, "src.modules.households.adjust_assets_and_expenditure": {"qualname": 4, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 99, "bases": 0, "doc": 100}, "src.modules.households.calculate_pml": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 75, "bases": 0, "doc": 65}, "src.modules.households.select_district": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 62, "bases": 0, "doc": 9}, "src.modules.households.estimate_savings": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 75, "bases": 0, "doc": 68}, "src.modules.households.set_vulnerability": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 76, "bases": 0, "doc": 72}, "src.modules.households.calculate_exposure": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 87, "bases": 0, "doc": 76}, "src.modules.households.determine_affected": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 48, "bases": 0, "doc": 95}, "src.modules.households.apply_individual_policy": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 45, "bases": 0, "doc": 99}, "src.modules.optimize": {"qualname": 0, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "src.modules.optimize.run_optimization": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 111, "bases": 0, "doc": 91}, "src.modules.optimize.optimize_recovery_rate": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 102, "bases": 0, "doc": 3}, "src.modules.optimize.integrate_wellbeing": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 157, "bases": 0, "doc": 3}}, "length": 69, "save": true}, "index": {"qualname": {"root": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.prepare.prepare_household_survey": {"tf": 1}}, "df": 3}}}}}, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"src.modules.households.calculate_average_productivity": {"tf": 1}}, "df": 1}}}}}}}}}}}, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "y": {"docs": {"src.data.analyse.get_policy_effectiveness_tab": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 2}}}, "y": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.data.prepare.polynomial_regression": {"tf": 1}}, "df": 1}}}}}}}}, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"src.data.prepare.calculate_poverty_attributes": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}}, "df": 3}}}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {"src.data.write.find_poor": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.start_pipeline": {"tf": 1}}, "df": 1}}}}}}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "t": {"docs": {"src.data.visualise.nine_quadrants_plot": {"tf": 1}}, "df": 1}}}, "e": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write.get_people_by_years_in_poverty": {"tf": 1}}, "df": 1}}}}}, "m": {"docs": {}, "df": 0, "l": {"docs": {"src.modules.households.calculate_pml": {"tf": 1}}, "df": 1}}}, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.analyse.get_spatial_outcomes": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}}, "df": 3}}}}}}}, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"src.data.prepare.rename_other_columns": {"tf": 1}}, "df": 1}}}}, "r": {"docs": {"src.data.prepare.get_bank_or_credit_union": {"tf": 1}}, "df": 1}, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1}}, "df": 1}}}}}, "e": {"docs": {"src.modules.optimize.optimize_recovery_rate": {"tf": 1}}, "df": 1}}}}}}}}, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 1}, "src.data.analyse.get_policy_effectiveness_tab": {"tf": 1}, "src.data.prepare.get_bank_or_credit_union": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.visualise.get_colors": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}}, "df": 7}}, "a": {"docs": {}, "df": 0, "p": {"docs": {"src.data.write.calculate_poverty_gap": {"tf": 1}}, "df": 1}}}, "s": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 1}}, "df": 1}}}}}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "y": {"docs": {"src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}}, "df": 2}}}}, "b": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.subset_columns": {"tf": 1}}, "df": 1}}}}}, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.start_pipeline": {"tf": 1}}, "df": 1}}}}, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"src.modules.households.select_district": {"tf": 1}}, "df": 1}}}}, "t": {"docs": {"src.modules.households.set_vulnerability": {"tf": 1}}, "df": 1}}, "a": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "s": {"docs": {"src.modules.households.estimate_savings": {"tf": 1}}, "df": 1}}}}}}}, "e": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.get_policy_effectiveness_tab": {"tf": 1}}, "df": 1}}}}}}}}}}}}, "x": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1}}, "df": 1}}}}}}}, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.calculate_exposure": {"tf": 1}}, "df": 1}}}}}, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 1}}}}}}}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.estimate_savings": {"tf": 1}}, "df": 1}}}}}}}}, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "b": {"docs": {"src.data.analyse.get_policy_effectiveness_tab": {"tf": 1}}, "df": 1}}}, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}}, "df": 3, "s": {"docs": {"src.data.prepare.rename_assets_column": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 2}}}, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.assign_housing_vulnerability": {"tf": 1}}, "df": 1}}}}}, "d": {"docs": {}, "df": 0, "d": {"docs": {"src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.prepare.add_housing_attributes": {"tf": 1}, "src.data.prepare.add_insurance_attributes": {"tf": 1}, "src.data.prepare.add_missing_columns": {"tf": 1}, "src.data.write.add_columns": {"tf": 1}}, "df": 5}, "j": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 1}}}}}, "t": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.prepare.calculate_household_attributes": {"tf": 1}, "src.data.prepare.decode_demographic_attributes": {"tf": 1}, "src.data.prepare.decode_income_attributes": {"tf": 1}, "src.data.prepare.calculate_income_attributes": {"tf": 1}, "src.data.prepare.decode_housing_attributes": {"tf": 1}, "src.data.prepare.add_housing_attributes": {"tf": 1}, "src.data.prepare.add_insurance_attributes": {"tf": 1}, "src.data.prepare.calculate_housing_attributes": {"tf": 1}, "src.data.prepare.calculate_poverty_attributes": {"tf": 1}}, "df": 9}}}}}}}}}, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1}}, "df": 2}}}}}}, "n": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}}, "df": 1}}}}, "d": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 1}}, "f": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"src.modules.households.determine_affected": {"tf": 1}}, "df": 1}}}}}}}, "p": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "y": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}}}}}, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}}, "df": 3}}}}, "t": {"docs": {}, "df": 0, "a": {"docs": {"src.data.prepare.load_data": {"tf": 1}, "src.data.visualise.bin_data": {"tf": 1}}, "df": 2}}}, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.decode_demographic_attributes": {"tf": 1}, "src.data.prepare.decode_income_attributes": {"tf": 1}, "src.data.prepare.decode_housing_attributes": {"tf": 1}}, "df": 3}}}}, "m": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {"src.data.prepare.decode_demographic_attributes": {"tf": 1}}, "df": 1}}}}}}}}}, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.determine_affected": {"tf": 1}}, "df": 1}}}}}}}}, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"src.modules.households.select_district": {"tf": 1}}, "df": 1, "s": {"docs": {"src.data.prepare.merge_districts": {"tf": 1}}, "df": 1}}}}}}}}, "u": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.duplicate_households": {"tf": 1}}, "df": 1}}}}}}}}}, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "d": {"docs": {"src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.prepare.calculate_household_attributes": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}}, "df": 3, "s": {"docs": {"src.modules.households.duplicate_households": {"tf": 1}}, "df": 1}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.data.prepare.decode_housing_attributes": {"tf": 1}, "src.data.prepare.add_housing_attributes": {"tf": 1}, "src.data.prepare.calculate_housing_attributes": {"tf": 1}, "src.data.prepare.assign_housing_vulnerability": {"tf": 1}}, "df": 4}}}}}}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {"src.data.prepare.load_data": {"tf": 1}}, "df": 1}}, "s": {"docs": {}, "df": 0, "s": {"docs": {"src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {"src.data.prepare.linear_regression": {"tf": 1}}, "df": 1}}}}}}, "i": {"docs": {}, "df": 0, "s": {"docs": {"src.data.prepare.add_is_rural_column": {"tf": 1}}, "df": 1}, "n": {"docs": {"src.data.write.get_people_by_years_in_poverty": {"tf": 1}}, "df": 1, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.decode_income_attributes": {"tf": 1}, "src.data.prepare.calculate_income_attributes": {"tf": 1}}, "df": 2}}}}, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.add_insurance_attributes": {"tf": 1}}, "df": 1}}}}}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {"src.model.initialize_model": {"tf": 1}}, "df": 1}}}}}}}}, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}}}}}}}}, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 1}}}}}}}}}, "r": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.data.prepare.add_is_rural_column": {"tf": 1}}, "df": 1}}}, "n": {"docs": {"src.model.run_model": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}}, "df": 2}}, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.rename_assets_column": {"tf": 1}, "src.data.prepare.rename_other_columns": {"tf": 1}}, "df": 2}}}}, "g": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}}, "df": 3}}}}}}}}, "a": {"docs": {}, "df": 0, "d": {"docs": {"src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}}, "df": 2}}, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write.calculate_resilience": {"tf": 1}}, "df": 1}}}}}}}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"src.modules.optimize.optimize_recovery_rate": {"tf": 1}}, "df": 1}}}}}}}, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "s": {"docs": {"src.data.visualise.rainclouds": {"tf": 1}}, "df": 1}}}}}}}}, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.optimize.optimize_recovery_rate": {"tf": 1}}, "df": 1}}}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.prepare.rename_assets_column": {"tf": 1}}, "df": 2, "s": {"docs": {"src.data.prepare.rename_other_columns": {"tf": 1}, "src.data.prepare.subset_columns": {"tf": 1}, "src.data.prepare.check_columns": {"tf": 1}, "src.data.prepare.add_missing_columns": {"tf": 1}, "src.data.write.add_columns": {"tf": 1}}, "df": 5}}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"src.data.visualise.get_colors": {"tf": 1}}, "df": 1}}}}, "n": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}}, "df": 1}}}}}}}}}}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.calculate_household_attributes": {"tf": 1}, "src.data.prepare.calculate_income_attributes": {"tf": 1}, "src.data.prepare.calculate_housing_attributes": {"tf": 1}, "src.data.prepare.calculate_poverty_attributes": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}}, "df": 10}}}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.get_bank_or_credit_union": {"tf": 1}}, "df": 1}}}}}, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "k": {"docs": {"src.data.prepare.check_columns": {"tf": 1}}, "df": 1}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"src.data.visualise.bivariate_choropleth": {"tf": 1}}, "df": 1}}}}}}}}}}, "b": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "k": {"docs": {"src.data.prepare.get_bank_or_credit_union": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.data.visualise.bivariate_choropleth": {"tf": 1}}, "df": 1}}}}}}}, "n": {"docs": {"src.data.visualise.bin_data": {"tf": 1}}, "df": 1}}, "y": {"docs": {"src.data.write.get_people_by_years_in_poverty": {"tf": 1}}, "df": 1}}, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.get_bank_or_credit_union": {"tf": 1}}, "df": 1}}}}}, "v": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"src.data.prepare.assign_housing_vulnerability": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}}, "df": 2}}}}}}}}}}}}}, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.data.prepare.add_missing_columns": {"tf": 1}}, "df": 1}}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.merge_districts": {"tf": 1}}, "df": 1}}}}, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "l": {"docs": {"src.model.initialize_model": {"tf": 1}, "src.model.run_model": {"tf": 1}}, "df": 2}}}}}, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"src.data.visualise.nine_quadrants_plot": {"tf": 1}}, "df": 1}}}}, "q": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"src.data.visualise.nine_quadrants_plot": {"tf": 1}}, "df": 1}}}}}}}}}, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {"src.data.write.find_poor": {"tf": 1}}, "df": 1}}}}, "y": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"src.data.write.get_people_by_years_in_poverty": {"tf": 1}}, "df": 1}}}}}, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 1}}}}}}}}}}}, "fullname": {"root": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {"src": {"tf": 1}, "src.data": {"tf": 1}, "src.data.analyse": {"tf": 1}, "src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.analyse.get_spatial_outcomes": {"tf": 1}, "src.data.analyse.get_policy_effectiveness_tab": {"tf": 1}, "src.data.prepare": {"tf": 1}, "src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.prepare.load_data": {"tf": 1}, "src.data.prepare.start_pipeline": {"tf": 1}, "src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.prepare.rename_assets_column": {"tf": 1}, "src.data.prepare.rename_other_columns": {"tf": 1}, "src.data.prepare.calculate_household_attributes": {"tf": 1}, "src.data.prepare.get_bank_or_credit_union": {"tf": 1}, "src.data.prepare.decode_demographic_attributes": {"tf": 1}, "src.data.prepare.decode_income_attributes": {"tf": 1}, "src.data.prepare.calculate_income_attributes": {"tf": 1}, "src.data.prepare.decode_housing_attributes": {"tf": 1}, "src.data.prepare.add_housing_attributes": {"tf": 1}, "src.data.prepare.add_insurance_attributes": {"tf": 1}, "src.data.prepare.calculate_housing_attributes": {"tf": 1}, "src.data.prepare.calculate_poverty_attributes": {"tf": 1}, "src.data.prepare.assign_housing_vulnerability": {"tf": 1}, "src.data.prepare.subset_columns": {"tf": 1}, "src.data.prepare.check_columns": {"tf": 1}, "src.data.prepare.add_missing_columns": {"tf": 1}, "src.data.prepare.merge_districts": {"tf": 1}, "src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.read": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.visualise": {"tf": 1}, "src.data.visualise.rainclouds": {"tf": 1}, "src.data.visualise.bivariate_choropleth": {"tf": 1}, "src.data.visualise.nine_quadrants_plot": {"tf": 1}, "src.data.visualise.get_colors": {"tf": 1}, "src.data.visualise.bin_data": {"tf": 1}, "src.data.write": {"tf": 1}, "src.data.write.add_columns": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.model": {"tf": 1}, "src.model.initialize_model": {"tf": 1}, "src.model.run_model": {"tf": 1}, "src.modules": {"tf": 1}, "src.modules.households": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.select_district": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}, "src.modules.optimize": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 69}}, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 1}}, "df": 1}}}}}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "y": {"docs": {"src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}}, "df": 2}}}}, "b": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.subset_columns": {"tf": 1}}, "df": 1}}}}}, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.start_pipeline": {"tf": 1}}, "df": 1}}}}, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"src.modules.households.select_district": {"tf": 1}}, "df": 1}}}}, "t": {"docs": {"src.modules.households.set_vulnerability": {"tf": 1}}, "df": 1}}, "a": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "s": {"docs": {"src.modules.households.estimate_savings": {"tf": 1}}, "df": 1}}}}}}}, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {"src.data": {"tf": 1}, "src.data.analyse": {"tf": 1}, "src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.analyse.get_spatial_outcomes": {"tf": 1}, "src.data.analyse.get_policy_effectiveness_tab": {"tf": 1}, "src.data.prepare": {"tf": 1}, "src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.prepare.load_data": {"tf": 1.4142135623730951}, "src.data.prepare.start_pipeline": {"tf": 1}, "src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.prepare.rename_assets_column": {"tf": 1}, "src.data.prepare.rename_other_columns": {"tf": 1}, "src.data.prepare.calculate_household_attributes": {"tf": 1}, "src.data.prepare.get_bank_or_credit_union": {"tf": 1}, "src.data.prepare.decode_demographic_attributes": {"tf": 1}, "src.data.prepare.decode_income_attributes": {"tf": 1}, "src.data.prepare.calculate_income_attributes": {"tf": 1}, "src.data.prepare.decode_housing_attributes": {"tf": 1}, "src.data.prepare.add_housing_attributes": {"tf": 1}, "src.data.prepare.add_insurance_attributes": {"tf": 1}, "src.data.prepare.calculate_housing_attributes": {"tf": 1}, "src.data.prepare.calculate_poverty_attributes": {"tf": 1}, "src.data.prepare.assign_housing_vulnerability": {"tf": 1}, "src.data.prepare.subset_columns": {"tf": 1}, "src.data.prepare.check_columns": {"tf": 1}, "src.data.prepare.add_missing_columns": {"tf": 1}, "src.data.prepare.merge_districts": {"tf": 1}, "src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.read": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.visualise": {"tf": 1}, "src.data.visualise.rainclouds": {"tf": 1}, "src.data.visualise.bivariate_choropleth": {"tf": 1}, "src.data.visualise.nine_quadrants_plot": {"tf": 1}, "src.data.visualise.get_colors": {"tf": 1}, "src.data.visualise.bin_data": {"tf": 1.4142135623730951}, "src.data.write": {"tf": 1}, "src.data.write.add_columns": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}}, "df": 49}}, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}}, "df": 3}}}}}, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.decode_demographic_attributes": {"tf": 1}, "src.data.prepare.decode_income_attributes": {"tf": 1}, "src.data.prepare.decode_housing_attributes": {"tf": 1}}, "df": 3}}}}, "m": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {"src.data.prepare.decode_demographic_attributes": {"tf": 1}}, "df": 1}}}}}}}}}, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.determine_affected": {"tf": 1}}, "df": 1}}}}}}}}, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"src.modules.households.select_district": {"tf": 1}}, "df": 1, "s": {"docs": {"src.data.prepare.merge_districts": {"tf": 1}}, "df": 1}}}}}}}}, "u": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.duplicate_households": {"tf": 1}}, "df": 1}}}}}}}}}, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"src.data.analyse": {"tf": 1}, "src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.analyse.get_spatial_outcomes": {"tf": 1}, "src.data.analyse.get_policy_effectiveness_tab": {"tf": 1}}, "df": 4}}}}}, "n": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}}, "df": 1}}}}, "d": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 1}}, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}}, "df": 3, "s": {"docs": {"src.data.prepare.rename_assets_column": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 2}}}, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.assign_housing_vulnerability": {"tf": 1}}, "df": 1}}}}}, "d": {"docs": {}, "df": 0, "d": {"docs": {"src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.prepare.add_housing_attributes": {"tf": 1}, "src.data.prepare.add_insurance_attributes": {"tf": 1}, "src.data.prepare.add_missing_columns": {"tf": 1}, "src.data.write.add_columns": {"tf": 1}}, "df": 5}, "j": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 1}}}}}, "t": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.prepare.calculate_household_attributes": {"tf": 1}, "src.data.prepare.decode_demographic_attributes": {"tf": 1}, "src.data.prepare.decode_income_attributes": {"tf": 1}, "src.data.prepare.calculate_income_attributes": {"tf": 1}, "src.data.prepare.decode_housing_attributes": {"tf": 1}, "src.data.prepare.add_housing_attributes": {"tf": 1}, "src.data.prepare.add_insurance_attributes": {"tf": 1}, "src.data.prepare.calculate_housing_attributes": {"tf": 1}, "src.data.prepare.calculate_poverty_attributes": {"tf": 1}}, "df": 9}}}}}}}}}, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1}}, "df": 2}}}}}}, "f": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"src.modules.households.determine_affected": {"tf": 1}}, "df": 1}}}}}}}, "p": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "y": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}}}}}, "p": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.prepare": {"tf": 1}, "src.data.prepare.prepare_asset_damage": {"tf": 1.4142135623730951}, "src.data.prepare.prepare_household_survey": {"tf": 1.4142135623730951}, "src.data.prepare.load_data": {"tf": 1}, "src.data.prepare.start_pipeline": {"tf": 1}, "src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.prepare.rename_assets_column": {"tf": 1}, "src.data.prepare.rename_other_columns": {"tf": 1}, "src.data.prepare.calculate_household_attributes": {"tf": 1}, "src.data.prepare.get_bank_or_credit_union": {"tf": 1}, "src.data.prepare.decode_demographic_attributes": {"tf": 1}, "src.data.prepare.decode_income_attributes": {"tf": 1}, "src.data.prepare.calculate_income_attributes": {"tf": 1}, "src.data.prepare.decode_housing_attributes": {"tf": 1}, "src.data.prepare.add_housing_attributes": {"tf": 1}, "src.data.prepare.add_insurance_attributes": {"tf": 1}, "src.data.prepare.calculate_housing_attributes": {"tf": 1}, "src.data.prepare.calculate_poverty_attributes": {"tf": 1}, "src.data.prepare.assign_housing_vulnerability": {"tf": 1}, "src.data.prepare.subset_columns": {"tf": 1}, "src.data.prepare.check_columns": {"tf": 1}, "src.data.prepare.add_missing_columns": {"tf": 1}, "src.data.prepare.merge_districts": {"tf": 1}, "src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}}, "df": 27}}}}}, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"src.modules.households.calculate_average_productivity": {"tf": 1}}, "df": 1}}}}}}}}}}}, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "y": {"docs": {"src.data.analyse.get_policy_effectiveness_tab": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 2}}}, "y": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.data.prepare.polynomial_regression": {"tf": 1}}, "df": 1}}}}}}}}, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"src.data.prepare.calculate_poverty_attributes": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}}, "df": 3}}}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {"src.data.write.find_poor": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.start_pipeline": {"tf": 1}}, "df": 1}}}}}}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "t": {"docs": {"src.data.visualise.nine_quadrants_plot": {"tf": 1}}, "df": 1}}}, "e": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write.get_people_by_years_in_poverty": {"tf": 1}}, "df": 1}}}}}, "m": {"docs": {}, "df": 0, "l": {"docs": {"src.modules.households.calculate_pml": {"tf": 1}}, "df": 1}}}, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.analyse.get_spatial_outcomes": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}}, "df": 3}}}}}}}, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"src.data.prepare.rename_other_columns": {"tf": 1}}, "df": 1}}}}, "r": {"docs": {"src.data.prepare.get_bank_or_credit_union": {"tf": 1}}, "df": 1}, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.optimize": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1.4142135623730951}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 4}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1}}, "df": 1}}}}}}}}}}}}, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 1}, "src.data.analyse.get_policy_effectiveness_tab": {"tf": 1}, "src.data.prepare.get_bank_or_credit_union": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.visualise.get_colors": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}}, "df": 7}}, "a": {"docs": {}, "df": 0, "p": {"docs": {"src.data.write.calculate_poverty_gap": {"tf": 1}}, "df": 1}}}, "e": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.get_policy_effectiveness_tab": {"tf": 1}}, "df": 1}}}}}}}}}}}}, "x": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1}}, "df": 1}}}}}}}, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.calculate_exposure": {"tf": 1}}, "df": 1}}}}}, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 1}}}}}}}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.estimate_savings": {"tf": 1}}, "df": 1}}}}}}}}, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "b": {"docs": {"src.data.analyse.get_policy_effectiveness_tab": {"tf": 1}}, "df": 1}}}, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "d": {"docs": {"src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.prepare.calculate_household_attributes": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}}, "df": 3, "s": {"docs": {"src.modules.households": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1.4142135623730951}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.select_district": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 11}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.data.prepare.decode_housing_attributes": {"tf": 1}, "src.data.prepare.add_housing_attributes": {"tf": 1}, "src.data.prepare.calculate_housing_attributes": {"tf": 1}, "src.data.prepare.assign_housing_vulnerability": {"tf": 1}}, "df": 4}}}}}}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {"src.data.prepare.load_data": {"tf": 1}}, "df": 1}}, "s": {"docs": {}, "df": 0, "s": {"docs": {"src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {"src.data.prepare.linear_regression": {"tf": 1}}, "df": 1}}}}}}, "i": {"docs": {}, "df": 0, "s": {"docs": {"src.data.prepare.add_is_rural_column": {"tf": 1}}, "df": 1}, "n": {"docs": {"src.data.write.get_people_by_years_in_poverty": {"tf": 1}}, "df": 1, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.decode_income_attributes": {"tf": 1}, "src.data.prepare.calculate_income_attributes": {"tf": 1}}, "df": 2}}}}, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.add_insurance_attributes": {"tf": 1}}, "df": 1}}}}}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {"src.model.initialize_model": {"tf": 1}}, "df": 1}}}}}}}}, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}}}}}}}}, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 1}}}}}}}}}, "r": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.data.prepare.add_is_rural_column": {"tf": 1}}, "df": 1}}}, "n": {"docs": {"src.model.run_model": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}}, "df": 2}}, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.rename_assets_column": {"tf": 1}, "src.data.prepare.rename_other_columns": {"tf": 1}}, "df": 2}}}}, "g": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}}, "df": 3}}}}}}}}, "a": {"docs": {}, "df": 0, "d": {"docs": {"src.data.read": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1.4142135623730951}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1.4142135623730951}}, "df": 4}}, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write.calculate_resilience": {"tf": 1}}, "df": 1}}}}}}}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"src.modules.optimize.optimize_recovery_rate": {"tf": 1}}, "df": 1}}}}}}}, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "s": {"docs": {"src.data.visualise.rainclouds": {"tf": 1}}, "df": 1}}}}}}}}, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.optimize.optimize_recovery_rate": {"tf": 1}}, "df": 1}}}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.prepare.rename_assets_column": {"tf": 1}}, "df": 2, "s": {"docs": {"src.data.prepare.rename_other_columns": {"tf": 1}, "src.data.prepare.subset_columns": {"tf": 1}, "src.data.prepare.check_columns": {"tf": 1}, "src.data.prepare.add_missing_columns": {"tf": 1}, "src.data.write.add_columns": {"tf": 1}}, "df": 5}}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"src.data.visualise.get_colors": {"tf": 1}}, "df": 1}}}}, "n": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}}, "df": 1}}}}}}}}}}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.calculate_household_attributes": {"tf": 1}, "src.data.prepare.calculate_income_attributes": {"tf": 1}, "src.data.prepare.calculate_housing_attributes": {"tf": 1}, "src.data.prepare.calculate_poverty_attributes": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}}, "df": 10}}}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.get_bank_or_credit_union": {"tf": 1}}, "df": 1}}}}}, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "k": {"docs": {"src.data.prepare.check_columns": {"tf": 1}}, "df": 1}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"src.data.visualise.bivariate_choropleth": {"tf": 1}}, "df": 1}}}}}}}}}}, "b": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "k": {"docs": {"src.data.prepare.get_bank_or_credit_union": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.data.visualise.bivariate_choropleth": {"tf": 1}}, "df": 1}}}}}}}, "n": {"docs": {"src.data.visualise.bin_data": {"tf": 1}}, "df": 1}}, "y": {"docs": {"src.data.write.get_people_by_years_in_poverty": {"tf": 1}}, "df": 1}}, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.get_bank_or_credit_union": {"tf": 1}}, "df": 1}}}}}, "v": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"src.data.prepare.assign_housing_vulnerability": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}}, "df": 2}}}}}}}}}}}}, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"src.data.visualise": {"tf": 1}, "src.data.visualise.rainclouds": {"tf": 1}, "src.data.visualise.bivariate_choropleth": {"tf": 1}, "src.data.visualise.nine_quadrants_plot": {"tf": 1}, "src.data.visualise.get_colors": {"tf": 1}, "src.data.visualise.bin_data": {"tf": 1}}, "df": 6}}}}}}}}}, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.data.prepare.add_missing_columns": {"tf": 1}}, "df": 1}}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.merge_districts": {"tf": 1}}, "df": 1}}}}, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "l": {"docs": {"src.model": {"tf": 1}, "src.model.initialize_model": {"tf": 1.4142135623730951}, "src.model.run_model": {"tf": 1.4142135623730951}}, "df": 3}}, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.modules": {"tf": 1}, "src.modules.households": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.select_district": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}, "src.modules.optimize": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 16}}}}}}}, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"src.data.visualise.nine_quadrants_plot": {"tf": 1}}, "df": 1}}}}, "q": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"src.data.visualise.nine_quadrants_plot": {"tf": 1}}, "df": 1}}}}}}}}}, "w": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write": {"tf": 1}, "src.data.write.add_columns": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}}, "df": 8}}}}, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 1}}}}}}}}}, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {"src.data.write.find_poor": {"tf": 1}}, "df": 1}}}}, "y": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"src.data.write.get_people_by_years_in_poverty": {"tf": 1}}, "df": 1}}}}}}}, "annotation": {"root": {"docs": {}, "df": 0}}, "default_value": {"root": {"docs": {}, "df": 0}}, "signature": {"root": {"0": {"docs": {"src.data.prepare.polynomial_regression": {"tf": 1}}, "df": 1}, "1": {"0": {"0": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1}}, "df": 2}, "docs": {}, "df": 0}, "docs": {}, "df": 0}, "3": {"9": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 2}, "src.data.visualise.rainclouds": {"tf": 1.4142135623730951}}, "df": 2}, "docs": {}, "df": 0}, "4": {"0": {"docs": {"src.data.prepare.polynomial_regression": {"tf": 1}}, "df": 1}, "docs": {}, "df": 0}, "docs": {"src.data.analyse.prepare_outcomes": {"tf": 6.855654600401044}, "src.data.analyse.get_spatial_outcomes": {"tf": 9.327379053088816}, "src.data.analyse.get_policy_effectiveness_tab": {"tf": 6.324555320336759}, "src.data.prepare.prepare_asset_damage": {"tf": 6.164414002968976}, "src.data.prepare.prepare_household_survey": {"tf": 4}, "src.data.prepare.load_data": {"tf": 5.830951894845301}, "src.data.prepare.start_pipeline": {"tf": 5.0990195135927845}, "src.data.prepare.add_is_rural_column": {"tf": 7.483314773547883}, "src.data.prepare.rename_assets_column": {"tf": 6.324555320336759}, "src.data.prepare.rename_other_columns": {"tf": 6.324555320336759}, "src.data.prepare.calculate_household_attributes": {"tf": 6.324555320336759}, "src.data.prepare.get_bank_or_credit_union": {"tf": 6.324555320336759}, "src.data.prepare.decode_demographic_attributes": {"tf": 6.324555320336759}, "src.data.prepare.decode_income_attributes": {"tf": 6.324555320336759}, "src.data.prepare.calculate_income_attributes": {"tf": 6.324555320336759}, "src.data.prepare.decode_housing_attributes": {"tf": 6.324555320336759}, "src.data.prepare.add_housing_attributes": {"tf": 6.324555320336759}, "src.data.prepare.add_insurance_attributes": {"tf": 6.324555320336759}, "src.data.prepare.calculate_housing_attributes": {"tf": 6.324555320336759}, "src.data.prepare.calculate_poverty_attributes": {"tf": 6.324555320336759}, "src.data.prepare.assign_housing_vulnerability": {"tf": 6.324555320336759}, "src.data.prepare.subset_columns": {"tf": 6.324555320336759}, "src.data.prepare.check_columns": {"tf": 6.324555320336759}, "src.data.prepare.add_missing_columns": {"tf": 7.0710678118654755}, "src.data.prepare.merge_districts": {"tf": 6.324555320336759}, "src.data.prepare.exponential_regression": {"tf": 10.246950765959598}, "src.data.prepare.polynomial_regression": {"tf": 12.529964086141668}, "src.data.prepare.linear_regression": {"tf": 10.488088481701515}, "src.data.read.read_asset_damage": {"tf": 3.4641016151377544}, "src.data.read.get_asset_damage": {"tf": 8.06225774829855}, "src.data.read.read_household_survey": {"tf": 5.291502622129181}, "src.data.visualise.rainclouds": {"tf": 10.723805294763608}, "src.data.visualise.bivariate_choropleth": {"tf": 6.164414002968976}, "src.data.visualise.nine_quadrants_plot": {"tf": 5.0990195135927845}, "src.data.visualise.get_colors": {"tf": 3.1622776601683795}, "src.data.visualise.bin_data": {"tf": 5.477225575051661}, "src.data.write.add_columns": {"tf": 7.874007874011811}, "src.data.write.get_outcomes": {"tf": 6.164414002968976}, "src.data.write.find_poor": {"tf": 6.855654600401044}, "src.data.write.get_people_by_years_in_poverty": {"tf": 5.291502622129181}, "src.data.write.calculate_poverty_gap": {"tf": 8.246211251235321}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 6}, "src.data.write.calculate_resilience": {"tf": 6}, "src.model.initialize_model": {"tf": 4.898979485566356}, "src.model.run_model": {"tf": 3.4641016151377544}, "src.modules.households.duplicate_households": {"tf": 7.0710678118654755}, "src.modules.households.calculate_average_productivity": {"tf": 6}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 8.774964387392123}, "src.modules.households.calculate_pml": {"tf": 7.681145747868608}, "src.modules.households.select_district": {"tf": 7.0710678118654755}, "src.modules.households.estimate_savings": {"tf": 7.681145747868608}, "src.modules.households.set_vulnerability": {"tf": 7.681145747868608}, "src.modules.households.calculate_exposure": {"tf": 8.246211251235321}, "src.modules.households.determine_affected": {"tf": 6.164414002968976}, "src.modules.households.apply_individual_policy": {"tf": 6}, "src.modules.optimize.run_optimization": {"tf": 9.273618495495704}, "src.modules.optimize.optimize_recovery_rate": {"tf": 8.888194417315589}, "src.modules.optimize.integrate_wellbeing": {"tf": 10.954451150103322}}, "df": 58, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}}, "df": 2}}}}}, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.visualise.bivariate_choropleth": {"tf": 1}}, "df": 5}}}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.estimate_savings": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 4}}, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {"src.modules.households.set_vulnerability": {"tf": 1}}, "df": 1}}}}}}, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.model.initialize_model": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 11}}}}, "r": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.load_data": {"tf": 1}, "src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.visualise.rainclouds": {"tf": 1}, "src.data.visualise.nine_quadrants_plot": {"tf": 1}, "src.data.visualise.bin_data": {"tf": 1}}, "df": 5}}, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 1}}}}}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.visualise.rainclouds": {"tf": 1}}, "df": 1}}}}, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "p": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}}, "df": 2}}}}}}}, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"src.data.visualise.bivariate_choropleth": {"tf": 1}}, "df": 1}}}}, "o": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 2}}}}}, "a": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "d": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1.4142135623730951}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 2}}, "g": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 1}}, "df": 1}}}}}}}}}}, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "y": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1.4142135623730951}, "src.data.prepare.polynomial_regression": {"tf": 1.4142135623730951}, "src.data.prepare.linear_regression": {"tf": 1.4142135623730951}}, "df": 3}}}}, "l": {"docs": {}, "df": 0, "l": {"docs": {"src.data.read.get_asset_damage": {"tf": 1}}, "df": 1}}, "f": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"src.data.write.add_columns": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 6}}}}}}}, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 2}}}}, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 4}}}}}}, "n": {"docs": {}, "df": 0, "d": {"docs": {"src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 1}}}, "p": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}}, "df": 1}}}, "y": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}}}}, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"src.data.prepare.polynomial_regression": {"tf": 1}}, "df": 1}}}, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"src.data.visualise.rainclouds": {"tf": 1}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 6}}}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {"src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1.4142135623730951}}, "df": 2}}}, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.analyse.get_spatial_outcomes": {"tf": 1}, "src.data.analyse.get_policy_effectiveness_tab": {"tf": 1.4142135623730951}, "src.data.prepare.load_data": {"tf": 1}, "src.data.prepare.start_pipeline": {"tf": 1}, "src.data.prepare.add_is_rural_column": {"tf": 1.4142135623730951}, "src.data.prepare.rename_assets_column": {"tf": 1.4142135623730951}, "src.data.prepare.rename_other_columns": {"tf": 1.4142135623730951}, "src.data.prepare.calculate_household_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.get_bank_or_credit_union": {"tf": 1.4142135623730951}, "src.data.prepare.decode_demographic_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.decode_income_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.calculate_income_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.decode_housing_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.add_housing_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.add_insurance_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.calculate_housing_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.calculate_poverty_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.assign_housing_vulnerability": {"tf": 1.4142135623730951}, "src.data.prepare.subset_columns": {"tf": 1.4142135623730951}, "src.data.prepare.check_columns": {"tf": 1.4142135623730951}, "src.data.prepare.add_missing_columns": {"tf": 1.4142135623730951}, "src.data.prepare.merge_districts": {"tf": 1.4142135623730951}, "src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.visualise.rainclouds": {"tf": 1}, "src.data.write.add_columns": {"tf": 1.7320508075688772}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1.4142135623730951}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1.4142135623730951}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.4142135623730951}, "src.modules.households.calculate_pml": {"tf": 1.4142135623730951}, "src.modules.households.select_district": {"tf": 1.4142135623730951}, "src.modules.households.estimate_savings": {"tf": 1.4142135623730951}, "src.modules.households.set_vulnerability": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1.4142135623730951}}, "df": 48}}}}, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.data.visualise.rainclouds": {"tf": 1}}, "df": 1}}}}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "s": {"docs": {"src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 4}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}}, "df": 2}}}}}, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.load_data": {"tf": 1}, "src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.visualise.bin_data": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}}, "df": 8}}}, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 4}}}}}}}}}}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "t": {"docs": {"src.data.visualise.rainclouds": {"tf": 1}}, "df": 1}}}, "m": {"docs": {}, "df": 0, "l": {"docs": {"src.data.write.calculate_resilience": {"tf": 1}}, "df": 1}}}, "b": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1.4142135623730951}, "src.data.prepare.load_data": {"tf": 1}, "src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.visualise.rainclouds": {"tf": 1.7320508075688772}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 13}}}, "u": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1.4142135623730951}, "src.data.prepare.linear_regression": {"tf": 1}}, "df": 3}}}}, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "s": {"docs": {"src.modules.households.calculate_exposure": {"tf": 1}}, "df": 1}}}}, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}}, "df": 1}}}}}}}}}}}}, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 3}}}}}}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.analyse.get_spatial_outcomes": {"tf": 1}, "src.data.analyse.get_policy_effectiveness_tab": {"tf": 1.4142135623730951}, "src.data.prepare.load_data": {"tf": 1}, "src.data.prepare.start_pipeline": {"tf": 1}, "src.data.prepare.add_is_rural_column": {"tf": 1.4142135623730951}, "src.data.prepare.rename_assets_column": {"tf": 1.4142135623730951}, "src.data.prepare.rename_other_columns": {"tf": 1.4142135623730951}, "src.data.prepare.calculate_household_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.get_bank_or_credit_union": {"tf": 1.4142135623730951}, "src.data.prepare.decode_demographic_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.decode_income_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.calculate_income_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.decode_housing_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.add_housing_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.add_insurance_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.calculate_housing_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.calculate_poverty_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.assign_housing_vulnerability": {"tf": 1.4142135623730951}, "src.data.prepare.subset_columns": {"tf": 1.4142135623730951}, "src.data.prepare.check_columns": {"tf": 1.4142135623730951}, "src.data.prepare.add_missing_columns": {"tf": 1.4142135623730951}, "src.data.prepare.merge_districts": {"tf": 1.4142135623730951}, "src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.visualise.rainclouds": {"tf": 1}, "src.data.write.add_columns": {"tf": 1.7320508075688772}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1.4142135623730951}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1.4142135623730951}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.4142135623730951}, "src.modules.households.calculate_pml": {"tf": 1.4142135623730951}, "src.modules.households.select_district": {"tf": 1.4142135623730951}, "src.modules.households.estimate_savings": {"tf": 1.4142135623730951}, "src.modules.households.set_vulnerability": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1.4142135623730951}}, "df": 48}}, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 1}, "src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.model.initialize_model": {"tf": 1}}, "df": 6}}}}}, "l": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1.4142135623730951}, "src.data.prepare.polynomial_regression": {"tf": 1.4142135623730951}, "src.data.prepare.linear_regression": {"tf": 1.4142135623730951}}, "df": 3, "s": {"docs": {"src.data.prepare.add_missing_columns": {"tf": 1}, "src.data.visualise.rainclouds": {"tf": 1}}, "df": 2}}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {"src.data.visualise.rainclouds": {"tf": 1}}, "df": 1}}}, "n": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 3}}}}}}}}}}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.calculate_exposure": {"tf": 1}}, "df": 1}}}}}}}, "s": {"docs": {}, "df": 0, "h": {"docs": {"src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 1}}}}, "f": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.analyse.get_spatial_outcomes": {"tf": 1}, "src.data.analyse.get_policy_effectiveness_tab": {"tf": 1.4142135623730951}, "src.data.prepare.load_data": {"tf": 1}, "src.data.prepare.start_pipeline": {"tf": 1}, "src.data.prepare.add_is_rural_column": {"tf": 1.4142135623730951}, "src.data.prepare.rename_assets_column": {"tf": 1.4142135623730951}, "src.data.prepare.rename_other_columns": {"tf": 1.4142135623730951}, "src.data.prepare.calculate_household_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.get_bank_or_credit_union": {"tf": 1.4142135623730951}, "src.data.prepare.decode_demographic_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.decode_income_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.calculate_income_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.decode_housing_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.add_housing_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.add_insurance_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.calculate_housing_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.calculate_poverty_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.assign_housing_vulnerability": {"tf": 1.4142135623730951}, "src.data.prepare.subset_columns": {"tf": 1.4142135623730951}, "src.data.prepare.check_columns": {"tf": 1.4142135623730951}, "src.data.prepare.add_missing_columns": {"tf": 1.4142135623730951}, "src.data.prepare.merge_districts": {"tf": 1.4142135623730951}, "src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.visualise.rainclouds": {"tf": 1}, "src.data.write.add_columns": {"tf": 1.7320508075688772}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1.4142135623730951}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1.4142135623730951}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.4142135623730951}, "src.modules.households.calculate_pml": {"tf": 1.4142135623730951}, "src.modules.households.select_district": {"tf": 1.4142135623730951}, "src.modules.households.estimate_savings": {"tf": 1.4142135623730951}, "src.modules.households.set_vulnerability": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1.4142135623730951}}, "df": 48}}, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}}, "df": 2}}}}}}}, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1.4142135623730951}, "src.data.prepare.linear_regression": {"tf": 1}}, "df": 3}}}}}}}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.visualise.rainclouds": {"tf": 1}}, "df": 3}}}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1.4142135623730951}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.7320508075688772}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 2}, "src.modules.optimize.optimize_recovery_rate": {"tf": 2.23606797749979}, "src.modules.optimize.integrate_wellbeing": {"tf": 2.23606797749979}}, "df": 13}}}}, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {"src.data.visualise.bivariate_choropleth": {"tf": 1}}, "df": 1}}}}}}}, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {"src.data.prepare.start_pipeline": {"tf": 1}, "src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.prepare.rename_assets_column": {"tf": 1}, "src.data.prepare.rename_other_columns": {"tf": 1}, "src.data.prepare.calculate_household_attributes": {"tf": 1}, "src.data.prepare.get_bank_or_credit_union": {"tf": 1}, "src.data.prepare.decode_demographic_attributes": {"tf": 1}, "src.data.prepare.decode_income_attributes": {"tf": 1}, "src.data.prepare.calculate_income_attributes": {"tf": 1}, "src.data.prepare.decode_housing_attributes": {"tf": 1}, "src.data.prepare.add_housing_attributes": {"tf": 1}, "src.data.prepare.add_insurance_attributes": {"tf": 1}, "src.data.prepare.calculate_housing_attributes": {"tf": 1}, "src.data.prepare.calculate_poverty_attributes": {"tf": 1}, "src.data.prepare.assign_housing_vulnerability": {"tf": 1}, "src.data.prepare.subset_columns": {"tf": 1}, "src.data.prepare.check_columns": {"tf": 1}, "src.data.prepare.add_missing_columns": {"tf": 1}, "src.data.prepare.merge_districts": {"tf": 1}, "src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.visualise.bivariate_choropleth": {"tf": 1}, "src.data.visualise.nine_quadrants_plot": {"tf": 1}, "src.data.visualise.get_colors": {"tf": 1}, "src.data.visualise.bin_data": {"tf": 1}}, "df": 26, "f": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.analyse.get_spatial_outcomes": {"tf": 1}, "src.data.analyse.get_policy_effectiveness_tab": {"tf": 1.4142135623730951}, "src.data.prepare.load_data": {"tf": 1}, "src.data.prepare.start_pipeline": {"tf": 1}, "src.data.prepare.add_is_rural_column": {"tf": 1.4142135623730951}, "src.data.prepare.rename_assets_column": {"tf": 1.4142135623730951}, "src.data.prepare.rename_other_columns": {"tf": 1.4142135623730951}, "src.data.prepare.calculate_household_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.get_bank_or_credit_union": {"tf": 1.4142135623730951}, "src.data.prepare.decode_demographic_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.decode_income_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.calculate_income_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.decode_housing_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.add_housing_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.add_insurance_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.calculate_housing_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.calculate_poverty_attributes": {"tf": 1.4142135623730951}, "src.data.prepare.assign_housing_vulnerability": {"tf": 1.4142135623730951}, "src.data.prepare.subset_columns": {"tf": 1.4142135623730951}, "src.data.prepare.check_columns": {"tf": 1.4142135623730951}, "src.data.prepare.add_missing_columns": {"tf": 1.4142135623730951}, "src.data.prepare.merge_districts": {"tf": 1.4142135623730951}, "src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.visualise.rainclouds": {"tf": 1}, "src.data.write.add_columns": {"tf": 1.7320508075688772}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1.4142135623730951}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1.4142135623730951}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.4142135623730951}, "src.modules.households.calculate_pml": {"tf": 1.4142135623730951}, "src.modules.households.select_district": {"tf": 1.4142135623730951}, "src.modules.households.estimate_savings": {"tf": 1.4142135623730951}, "src.modules.households.set_vulnerability": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1.4142135623730951}}, "df": 48}}}}}}}, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"src.data.read.get_asset_damage": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}}, "df": 2}}}}}, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"src.data.read.get_asset_damage": {"tf": 1}, "src.modules.households.select_district": {"tf": 1}}, "df": 2}}}}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 3}}}}}}, "c": {"docs": {}, "df": 0, "t": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 7}}}, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.determine_affected": {"tf": 1}}, "df": 1}}}}}}}}}, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 1.4142135623730951}, "src.data.analyse.get_policy_effectiveness_tab": {"tf": 1}, "src.data.visualise.rainclouds": {"tf": 1}}, "df": 3}}}}}}}, "f": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 1}}, "df": 1}, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1.4142135623730951}}, "df": 2}}}}}}}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1.4142135623730951}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.visualise.rainclouds": {"tf": 1}}, "df": 4, "t": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 2}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.model.initialize_model": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 11, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 1}}, "df": 1}}}}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.data.write.calculate_poverty_gap": {"tf": 1}}, "df": 1}}}}}, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 1}}}}}}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.optimize.integrate_wellbeing": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "s": {"docs": {"src.modules.households.set_vulnerability": {"tf": 1}}, "df": 1}}, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 1}, "src.data.prepare.add_missing_columns": {"tf": 1}, "src.data.visualise.rainclouds": {"tf": 1.4142135623730951}}, "df": 3}}, "n": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write.find_poor": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.4142135623730951}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 4}}}, "u": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 1}}, "df": 1}}}}, "t": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1.4142135623730951}, "src.data.prepare.linear_regression": {"tf": 1}}, "df": 3}, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "l": {"docs": {"src.data.visualise.bivariate_choropleth": {"tf": 1.4142135623730951}}, "df": 1}}}}, "o": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 3}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 1.4142135623730951}, "src.data.prepare.prepare_asset_damage": {"tf": 1.4142135623730951}, "src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.prepare.exponential_regression": {"tf": 1.4142135623730951}, "src.data.prepare.polynomial_regression": {"tf": 1.4142135623730951}, "src.data.prepare.linear_regression": {"tf": 1.4142135623730951}, "src.data.read.get_asset_damage": {"tf": 1.4142135623730951}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.visualise.rainclouds": {"tf": 1}, "src.model.initialize_model": {"tf": 1}, "src.modules.households.select_district": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 12}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "s": {"docs": {"src.data.prepare.load_data": {"tf": 1}, "src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.visualise.bin_data": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}}, "df": 8}}}}}}}, "r": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.polynomial_regression": {"tf": 1}}, "df": 1}}}, "o": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "k": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 2}}}}, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 1}}, "df": 1}}}, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "s": {"docs": {"src.data.visualise.rainclouds": {"tf": 1}}, "df": 1}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.modules.households.estimate_savings": {"tf": 1}}, "df": 1, "s": {"docs": {"src.modules.households.estimate_savings": {"tf": 1}}, "df": 1}}}}}}, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.visualise.bivariate_choropleth": {"tf": 1}, "src.data.visualise.nine_quadrants_plot": {"tf": 1}, "src.data.visualise.bin_data": {"tf": 1}}, "df": 5}}}}, "e": {"docs": {}, "df": 0, "t": {"2": {"docs": {"src.data.visualise.rainclouds": {"tf": 1}}, "df": 1}, "docs": {"src.modules.households.set_vulnerability": {"tf": 1}}, "df": 1}}, "h": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {"src.data.visualise.rainclouds": {"tf": 1}}, "df": 1}}}}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "y": {"docs": {"src.modules.households.duplicate_households": {"tf": 1}, "src.modules.households.select_district": {"tf": 1}}, "df": 2}}}}}}, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.data.prepare.add_missing_columns": {"tf": 1}}, "df": 1}}}}}, "n": {"docs": {"src.model.initialize_model": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1}}, "df": 2}}, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "l": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}}, "df": 2}}}}, "y": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}}, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 1}}, "df": 1}}}}}}, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"src.data.analyse.get_spatial_outcomes": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}}}}}, "t": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1.4142135623730951}, "src.data.prepare.linear_regression": {"tf": 1}}, "df": 3}, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 1}}}}}}, "n": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 7, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1.4142135623730951}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}}, "df": 6}}}, "u": {"docs": {}, "df": 0, "m": {"docs": {"src.data.prepare.polynomial_regression": {"tf": 1}}, "df": 1, "p": {"docs": {}, "df": 0, "y": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}}, "df": 2}}}}, "e": {"docs": {}, "df": 0, "w": {"docs": {"src.data.prepare.polynomial_regression": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}}, "df": 3}}, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"src.data.visualise.bivariate_choropleth": {"tf": 1.4142135623730951}, "src.data.visualise.nine_quadrants_plot": {"tf": 1.4142135623730951}, "src.data.visualise.bin_data": {"tf": 1.4142135623730951}}, "df": 3}}}}, "x": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 2.23606797749979}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.visualise.rainclouds": {"tf": 1.4142135623730951}, "src.data.visualise.bivariate_choropleth": {"tf": 1.4142135623730951}, "src.data.visualise.nine_quadrants_plot": {"tf": 1}, "src.data.visualise.bin_data": {"tf": 1}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}}, "df": 8}, "y": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.visualise.bivariate_choropleth": {"tf": 1.4142135623730951}, "src.data.visualise.nine_quadrants_plot": {"tf": 1}, "src.data.visualise.bin_data": {"tf": 1}}, "df": 6, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"src.data.visualise.rainclouds": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 8}}}}}, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"src.data.prepare.exponential_regression": {"tf": 1}, "src.data.prepare.polynomial_regression": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}}, "df": 3}}}}}}}, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {"src.data.prepare.polynomial_regression": {"tf": 1}}, "df": 1}}, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"src.data.write.get_outcomes": {"tf": 1}}, "df": 1}}}}, "x": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}}, "df": 2}}}}, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 1}}}}}}}}, "o": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.calculate_exposure": {"tf": 1}}, "df": 1}}}}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.estimate_savings": {"tf": 1}}, "df": 1}}}}}}}}, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "d": {"docs": {"src.modules.households.duplicate_households": {"tf": 1}, "src.modules.households.select_district": {"tf": 1}}, "df": 2, "s": {"docs": {"src.data.write.add_columns": {"tf": 1.4142135623730951}, "src.data.write.get_outcomes": {"tf": 1}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.model.initialize_model": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}, "src.modules.optimize.integrate_wellbeing": {"tf": 1}}, "df": 17}}}}}}}}}}, "k": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "s": {"docs": {"src.model.run_model": {"tf": 1}}, "df": 1}}}}}}, "v": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"src.modules.households.set_vulnerability": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}}}}}}}}}, "bases": {"root": {"docs": {}, "df": 0}}, "doc": {"root": {"0": {"docs": {"src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1.4142135623730951}}, "df": 2}, "1": {"0": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}, "docs": {"src.data.read.get_asset_damage": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}}, "df": 4}, "2": {"5": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}, "docs": {}, "df": 0}, "3": {"0": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}, "docs": {}, "df": 0}, "5": {"0": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}, "docs": {}, "df": 0}, "docs": {"src": {"tf": 1.7320508075688772}, "src.data": {"tf": 1.7320508075688772}, "src.data.analyse": {"tf": 1.7320508075688772}, "src.data.analyse.prepare_outcomes": {"tf": 3.4641016151377544}, "src.data.analyse.get_spatial_outcomes": {"tf": 1.7320508075688772}, "src.data.analyse.get_policy_effectiveness_tab": {"tf": 1.7320508075688772}, "src.data.prepare": {"tf": 1.7320508075688772}, "src.data.prepare.prepare_asset_damage": {"tf": 1.7320508075688772}, "src.data.prepare.prepare_household_survey": {"tf": 3.605551275463989}, "src.data.prepare.load_data": {"tf": 1.7320508075688772}, "src.data.prepare.start_pipeline": {"tf": 1.7320508075688772}, "src.data.prepare.add_is_rural_column": {"tf": 1.7320508075688772}, "src.data.prepare.rename_assets_column": {"tf": 1.7320508075688772}, "src.data.prepare.rename_other_columns": {"tf": 1.7320508075688772}, "src.data.prepare.calculate_household_attributes": {"tf": 1.7320508075688772}, "src.data.prepare.get_bank_or_credit_union": {"tf": 1.7320508075688772}, "src.data.prepare.decode_demographic_attributes": {"tf": 1.7320508075688772}, "src.data.prepare.decode_income_attributes": {"tf": 1.7320508075688772}, "src.data.prepare.calculate_income_attributes": {"tf": 1.7320508075688772}, "src.data.prepare.decode_housing_attributes": {"tf": 1.7320508075688772}, "src.data.prepare.add_housing_attributes": {"tf": 1.7320508075688772}, "src.data.prepare.add_insurance_attributes": {"tf": 1.7320508075688772}, "src.data.prepare.calculate_housing_attributes": {"tf": 1.7320508075688772}, "src.data.prepare.calculate_poverty_attributes": {"tf": 1.7320508075688772}, "src.data.prepare.assign_housing_vulnerability": {"tf": 1.7320508075688772}, "src.data.prepare.subset_columns": {"tf": 1.7320508075688772}, "src.data.prepare.check_columns": {"tf": 1.7320508075688772}, "src.data.prepare.add_missing_columns": {"tf": 1.7320508075688772}, "src.data.prepare.merge_districts": {"tf": 1.7320508075688772}, "src.data.prepare.exponential_regression": {"tf": 1.7320508075688772}, "src.data.prepare.polynomial_regression": {"tf": 1.7320508075688772}, "src.data.prepare.linear_regression": {"tf": 1.7320508075688772}, "src.data.read": {"tf": 1.7320508075688772}, "src.data.read.read_asset_damage": {"tf": 1.7320508075688772}, "src.data.read.get_asset_damage": {"tf": 4.795831523312719}, "src.data.read.read_household_survey": {"tf": 3.872983346207417}, "src.data.visualise": {"tf": 1.7320508075688772}, "src.data.visualise.rainclouds": {"tf": 1.7320508075688772}, "src.data.visualise.bivariate_choropleth": {"tf": 1.7320508075688772}, "src.data.visualise.nine_quadrants_plot": {"tf": 1.7320508075688772}, "src.data.visualise.get_colors": {"tf": 1.7320508075688772}, "src.data.visualise.bin_data": {"tf": 1.7320508075688772}, "src.data.write": {"tf": 1.7320508075688772}, "src.data.write.add_columns": {"tf": 2.6457513110645907}, "src.data.write.get_outcomes": {"tf": 3.872983346207417}, "src.data.write.find_poor": {"tf": 2.8284271247461903}, "src.data.write.get_people_by_years_in_poverty": {"tf": 2.8284271247461903}, "src.data.write.calculate_poverty_gap": {"tf": 3.605551275463989}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 3.3166247903554}, "src.data.write.calculate_resilience": {"tf": 3.3166247903554}, "src.model": {"tf": 1.7320508075688772}, "src.model.initialize_model": {"tf": 3.3166247903554}, "src.model.run_model": {"tf": 1.7320508075688772}, "src.modules": {"tf": 1.7320508075688772}, "src.modules.households": {"tf": 1.7320508075688772}, "src.modules.households.duplicate_households": {"tf": 4}, "src.modules.households.calculate_average_productivity": {"tf": 3.4641016151377544}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 4.123105625617661}, "src.modules.households.calculate_pml": {"tf": 3.4641016151377544}, "src.modules.households.select_district": {"tf": 1.7320508075688772}, "src.modules.households.estimate_savings": {"tf": 3.872983346207417}, "src.modules.households.set_vulnerability": {"tf": 4.358898943540674}, "src.modules.households.calculate_exposure": {"tf": 4}, "src.modules.households.determine_affected": {"tf": 4.58257569495584}, "src.modules.households.apply_individual_policy": {"tf": 5.0990195135927845}, "src.modules.optimize": {"tf": 1.7320508075688772}, "src.modules.optimize.run_optimization": {"tf": 3.872983346207417}, "src.modules.optimize.optimize_recovery_rate": {"tf": 1.7320508075688772}, "src.modules.optimize.integrate_wellbeing": {"tf": 1.7320508075688772}}, "df": 69, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}}, "df": 1}}}}, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"src.data.write.get_outcomes": {"tf": 1}}, "df": 1}}}}, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.data.write.calculate_average_annual_consumption_loss": {"tf": 2.6457513110645907}, "src.data.write.calculate_resilience": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}}, "df": 3}}}}}}}}, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}}, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"src.data.prepare.prepare_household_survey": {"tf": 1.4142135623730951}, "src.data.read.read_household_survey": {"tf": 1.7320508075688772}, "src.model.initialize_model": {"tf": 1.4142135623730951}}, "df": 3}}}}}, "l": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.prepare.rename_assets_column": {"tf": 1}}, "df": 2, "s": {"docs": {"src.data.prepare.rename_other_columns": {"tf": 1}, "src.data.prepare.subset_columns": {"tf": 1}, "src.data.prepare.add_missing_columns": {"tf": 1}}, "df": 3, "/": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.write.add_columns": {"tf": 1}}, "df": 1}}}}}}}}}}}}}}, "e": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.linear_regression": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}}, "df": 2}}}}}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.add_is_rural_column": {"tf": 1}}, "df": 1, "d": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 1}}}}}}, "s": {"docs": {}, "df": 0, "v": {"docs": {"src.data.read.read_household_survey": {"tf": 1}}, "df": 1}}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 7, "d": {"docs": {"src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 2}, "s": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1}}, "df": 1}}, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {"src.data.write.get_outcomes": {"tf": 1}}, "df": 1}}}, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.modules.households.calculate_exposure": {"tf": 1}}, "df": 1}}}}}}}}}, "n": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 3}, "p": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}}, "df": 2}}}}}}}, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1.4142135623730951}, "src.data.write.get_outcomes": {"tf": 1.4142135623730951}}, "df": 2}}}}}}}, "f": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.prepare.rename_other_columns": {"tf": 1}, "src.data.prepare.subset_columns": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.write.add_columns": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1.7320508075688772}, "src.data.write.find_poor": {"tf": 2.449489742783178}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1.4142135623730951}, "src.data.write.calculate_poverty_gap": {"tf": 2.449489742783178}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 2}, "src.data.write.calculate_resilience": {"tf": 1.4142135623730951}, "src.model.initialize_model": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1.4142135623730951}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.7320508075688772}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1.4142135623730951}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}}, "df": 21}, "r": {"docs": {"src.data.prepare.add_is_rural_column": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 3}, "n": {"docs": {"src.data.prepare.linear_regression": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 3, "l": {"docs": {}, "df": 0, "y": {"docs": {"src.data.read.get_asset_damage": {"tf": 1}}, "df": 1}}}, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1.7320508075688772}}, "df": 4}}}}}}}}, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}}, "df": 3}}}}}}}}, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 6}}, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 2.23606797749979}, "src.modules.households.select_district": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 8, "s": {"docs": {"src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}}, "df": 2}}}, "b": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.modules.households.set_vulnerability": {"tf": 1}}, "df": 1}}}}}}}}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 2}, "src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.prepare.load_data": {"tf": 1}, "src.data.prepare.start_pipeline": {"tf": 1}, "src.data.prepare.add_missing_columns": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1.4142135623730951}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 2}, "src.modules.households.calculate_pml": {"tf": 1.4142135623730951}, "src.modules.households.estimate_savings": {"tf": 1.4142135623730951}, "src.modules.households.set_vulnerability": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1.4142135623730951}, "src.modules.households.apply_individual_policy": {"tf": 1.4142135623730951}, "src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}}, "df": 20, "f": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.write.add_columns": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}, "src.data.write.find_poor": {"tf": 1.7320508075688772}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1.4142135623730951}, "src.data.write.calculate_poverty_gap": {"tf": 1.4142135623730951}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1.4142135623730951}, "src.data.write.calculate_resilience": {"tf": 1.4142135623730951}, "src.modules.households.duplicate_households": {"tf": 1.4142135623730951}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.4142135623730951}, "src.modules.households.calculate_pml": {"tf": 1.4142135623730951}, "src.modules.households.estimate_savings": {"tf": 1.4142135623730951}, "src.modules.households.set_vulnerability": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}}, "df": 20}}}}}}}, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 2}, "src.data.write.get_outcomes": {"tf": 1.4142135623730951}, "src.model.initialize_model": {"tf": 1.4142135623730951}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.4142135623730951}}, "df": 6}}}}}, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.rename_assets_column": {"tf": 1}}, "df": 1}}}}}}}}}, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "s": {"docs": {"src.data.prepare.rename_other_columns": {"tf": 1}}, "df": 1}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.determine_affected": {"tf": 1}}, "df": 1, "s": {"docs": {"src.modules.households.determine_affected": {"tf": 1}}, "df": 1}, "d": {"docs": {"src.modules.households.determine_affected": {"tf": 1}}, "df": 1}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.modules.households.determine_affected": {"tf": 1}}, "df": 1}}}}}}}}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.decode_demographic_attributes": {"tf": 1}, "src.data.prepare.decode_income_attributes": {"tf": 1}, "src.data.prepare.decode_housing_attributes": {"tf": 1}}, "df": 3}}}}, "m": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {"src.data.prepare.decode_demographic_attributes": {"tf": 1}}, "df": 1}}}}}}}}}, "f": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}}, "df": 3}}}}}}}, "o": {"docs": {"src.data.prepare.linear_regression": {"tf": 1}}, "df": 1}, "u": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"src.data.write.calculate_poverty_gap": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1}}, "df": 2}, "s": {"docs": {"src.modules.households.duplicate_households": {"tf": 1}}, "df": 1}}, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.modules.households.duplicate_households": {"tf": 1}}, "df": 1}}}}}}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 2}, "src.model.initialize_model": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}}, "df": 7, "t": {"docs": {"src.data.read.get_asset_damage": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.model.initialize_model": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}}, "df": 6, "o": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}}, "df": 3}, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.add_housing_attributes": {"tf": 1}}, "df": 1}}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.subset_columns": {"tf": 1}, "src.data.write.add_columns": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1.4142135623730951}}, "df": 3}}}}}}, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.prepare.add_is_rural_column": {"tf": 1}}, "df": 1}}}}}, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1.4142135623730951}}, "df": 1}}}}}}, "e": {"docs": {}, "df": 0, "x": {"docs": {"src.data.write.calculate_poverty_gap": {"tf": 1}}, "df": 1}, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "y": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 1}}}}}}}}}}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.decode_income_attributes": {"tf": 1}}, "df": 1}}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {"src.modules.households.set_vulnerability": {"tf": 1}}, "df": 1, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.data.write.calculate_poverty_gap": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1}}, "df": 2, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {"src.model.initialize_model": {"tf": 1}}, "df": 1}}}}}}}}}, "t": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}}, "df": 2}, "f": {"docs": {"src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1.4142135623730951}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1.4142135623730951}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1.4142135623730951}, "src.modules.households.set_vulnerability": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1.4142135623730951}}, "df": 10}, "s": {"docs": {"src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1.7320508075688772}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1.4142135623730951}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1.4142135623730951}, "src.modules.households.duplicate_households": {"tf": 1.4142135623730951}, "src.modules.households.set_vulnerability": {"tf": 1.7320508075688772}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 12}}, "a": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.prepare.rename_other_columns": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1.4142135623730951}, "src.model.initialize_model": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.select_district": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1.4142135623730951}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 2}, "src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}}, "df": 19, "r": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.model.initialize_model": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}}, "df": 20}}, "e": {"docs": {"src.modules.households.estimate_savings": {"tf": 1}}, "df": 1}}, "d": {"docs": {}, "df": 0, "d": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 2}, "src.data.prepare.add_missing_columns": {"tf": 1}, "src.data.write.add_columns": {"tf": 1}}, "df": 3}, "j": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 1, "e": {"docs": {}, "df": 0, "d": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 1}}}}}}}, "s": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1.4142135623730951}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}}, "df": 4, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1.7320508075688772}, "src.data.write.get_outcomes": {"tf": 1.4142135623730951}, "src.model.initialize_model": {"tf": 1.4142135623730951}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 2}, "src.modules.households.determine_affected": {"tf": 1.4142135623730951}}, "df": 7, "s": {"docs": {"src.data.prepare.rename_assets_column": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.4142135623730951}}, "df": 2}}}, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 2}}}, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"src.modules.households.set_vulnerability": {"tf": 1}}, "df": 1}}}}}}}, "n": {"docs": {}, "df": 0, "d": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 1.4142135623730951}, "src.data.read.read_asset_damage": {"tf": 1}, "src.data.write.find_poor": {"tf": 1.4142135623730951}, "src.data.write.calculate_poverty_gap": {"tf": 1.4142135623730951}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1.4142135623730951}, "src.data.write.calculate_resilience": {"tf": 1}, "src.model.initialize_model": {"tf": 1.4142135623730951}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.7320508075688772}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1.4142135623730951}}, "df": 14}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {"src.data.read.get_asset_damage": {"tf": 1}}, "df": 1}}}}}}, "n": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.data.write.calculate_average_annual_consumption_loss": {"tf": 2.6457513110645907}}, "df": 1}}}}}, "t": {"docs": {"src.data.write.find_poor": {"tf": 2}, "src.data.write.calculate_poverty_gap": {"tf": 2.449489742783178}}, "df": 2, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.prepare.decode_demographic_attributes": {"tf": 1}, "src.data.prepare.decode_income_attributes": {"tf": 1}, "src.data.prepare.decode_housing_attributes": {"tf": 1}, "src.data.prepare.add_housing_attributes": {"tf": 1}}, "df": 4}}}}}}}}}, "l": {"docs": {}, "df": 0, "l": {"docs": {"src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 4}, "g": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "m": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}}, "df": 4}}}}}}}}, "f": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"src.data.write.add_columns": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1.4142135623730951}, "src.data.write.calculate_resilience": {"tf": 1.7320508075688772}, "src.modules.households.determine_affected": {"tf": 2.23606797749979}, "src.modules.households.apply_individual_policy": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 2}}, "df": 6}}}}}}, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"src.modules.households.duplicate_households": {"tf": 1}}, "df": 1}}}}, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write.get_outcomes": {"tf": 1.4142135623730951}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 2.6457513110645907}, "src.modules.households.calculate_average_productivity": {"tf": 1.7320508075688772}, "src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}}, "df": 4}}}, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1}}, "df": 1}}}}}}}, "e": {"docs": {"src.modules.households.calculate_average_productivity": {"tf": 1}}, "df": 1, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {"src.modules.households.calculate_average_productivity": {"tf": 1}}, "df": 1}}}}, "p": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "y": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1.4142135623730951}}, "df": 1}, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}}}}}}}, "f": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 2}, "src.data.write.get_outcomes": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}}, "df": 3}}, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.data.read.get_asset_damage": {"tf": 1.4142135623730951}, "src.data.write.get_outcomes": {"tf": 1.4142135623730951}, "src.modules.households.calculate_pml": {"tf": 1.7320508075688772}}, "df": 3}}}}}}, "o": {"docs": {}, "df": 0, "m": {"docs": {"src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.write.add_columns": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}}, "df": 4}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {"src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.prepare.rename_other_columns": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1.4142135623730951}, "src.data.write.get_outcomes": {"tf": 1.4142135623730951}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1.4142135623730951}, "src.modules.households.select_district": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1.4142135623730951}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1.7320508075688772}, "src.modules.households.apply_individual_policy": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}}, "df": 13, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}}, "df": 1}}}}, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {"src.modules.households.determine_affected": {"tf": 1}}, "df": 1}}}}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 4, "s": {"docs": {"src.model.initialize_model": {"tf": 1.4142135623730951}}, "df": 1}}}}, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.rename_other_columns": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}}, "df": 5}}}}}}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {"src.data.write.get_outcomes": {"tf": 2.23606797749979}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.7320508075688772}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 2}}, "df": 10}}}}, "a": {"docs": {"src.modules.households.determine_affected": {"tf": 1}}, "df": 1, "l": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}}, "df": 3}}}}}, "r": {"2": {"docs": {"src.data.prepare.linear_regression": {"tf": 1}}, "df": 1}, "docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1.4142135623730951}}, "df": 1}}}}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write.calculate_resilience": {"tf": 1.7320508075688772}}, "df": 1}}}}}}}}, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.linear_regression": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1.4142135623730951}}, "df": 2, "s": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.model.initialize_model": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}}, "df": 20}}}}}, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.rename_assets_column": {"tf": 1}, "src.data.prepare.rename_other_columns": {"tf": 1}}, "df": 2}}}}, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"src.data.prepare.decode_income_attributes": {"tf": 1}, "src.data.prepare.decode_housing_attributes": {"tf": 1}}, "df": 2}}, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1}}, "df": 1}}}}}}, "g": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.linear_regression": {"tf": 1}}, "df": 1}}}}}}}}, "a": {"docs": {}, "df": 0, "d": {"docs": {"src.data.read.read_asset_damage": {"tf": 1}}, "df": 1, "s": {"docs": {"src.data.read.read_household_survey": {"tf": 1}}, "df": 1}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.model.initialize_model": {"tf": 1}}, "df": 1}}}}}, "p": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"src.model.initialize_model": {"tf": 1}}, "df": 1}}}}}}}}}}}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 9}}}}, "w": {"docs": {"src.data.prepare.load_data": {"tf": 1}}, "df": 1}, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.estimate_savings": {"tf": 1.7320508075688772}, "src.modules.optimize.run_optimization": {"tf": 2}}, "df": 2}}, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {"src.modules.households.set_vulnerability": {"tf": 1.7320508075688772}}, "df": 1}}}}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.data.prepare.add_is_rural_column": {"tf": 1}}, "df": 1}}}, "n": {"docs": {"src.model.run_model": {"tf": 1}}, "df": 1}}, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "k": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1}}, "df": 1}}}}, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.model.initialize_model": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 9}}}}, "h": {"docs": {}, "df": 0, "e": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 2.23606797749979}, "src.data.prepare.prepare_household_survey": {"tf": 1.4142135623730951}, "src.data.prepare.load_data": {"tf": 1}, "src.data.prepare.start_pipeline": {"tf": 1}, "src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.prepare.rename_assets_column": {"tf": 1}, "src.data.prepare.decode_demographic_attributes": {"tf": 1}, "src.data.prepare.decode_income_attributes": {"tf": 1}, "src.data.prepare.decode_housing_attributes": {"tf": 1}, "src.data.prepare.add_missing_columns": {"tf": 1}, "src.data.prepare.linear_regression": {"tf": 2}, "src.data.read.read_asset_damage": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 2}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.write.add_columns": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}, "src.data.write.find_poor": {"tf": 3.3166247903554}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 3.7416573867739413}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 2}, "src.data.write.calculate_resilience": {"tf": 1.7320508075688772}, "src.model.initialize_model": {"tf": 1}, "src.model.run_model": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1.7320508075688772}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 2.449489742783178}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1.7320508075688772}, "src.modules.optimize.run_optimization": {"tf": 3.3166247903554}}, "df": 31, "r": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 1}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.add_is_rural_column": {"tf": 1}, "src.model.initialize_model": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 4}, "n": {"docs": {"src.data.read.get_asset_damage": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 6}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "d": {"docs": {"src.modules.households.duplicate_households": {"tf": 1}}, "df": 1}}}}}}}, "i": {"docs": {}, "df": 0, "s": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1}}, "df": 1}}}, "o": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 2}, "src.data.prepare.rename_assets_column": {"tf": 1}, "src.data.prepare.add_missing_columns": {"tf": 1}, "src.data.write.add_columns": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}, "src.model.initialize_model": {"tf": 1.4142135623730951}, "src.modules.households.duplicate_households": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1.4142135623730951}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.7320508075688772}, "src.modules.households.calculate_pml": {"tf": 1.4142135623730951}, "src.modules.households.apply_individual_policy": {"tf": 1.4142135623730951}}, "df": 11, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.data.read.get_asset_damage": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1.4142135623730951}, "src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1.4142135623730951}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 6}}}, "p": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1.4142135623730951}}, "df": 1}}, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.write.calculate_resilience": {"tf": 1}}, "df": 1, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "p": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}, "r": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}}, "df": 2}}}, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1.7320508075688772}}, "df": 1}}}}}}, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}}, "df": 1}}}}}}}, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"src.data.read.get_asset_damage": {"tf": 1.4142135623730951}, "src.data.write.get_outcomes": {"tf": 1.4142135623730951}, "src.modules.households.calculate_pml": {"tf": 1.7320508075688772}}, "df": 3}}}}, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1.4142135623730951}, "src.modules.households.estimate_savings": {"tf": 1}}, "df": 2}}}}}}}}, "o": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.calculate_exposure": {"tf": 2.23606797749979}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 2}}}}}}, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.data.write.calculate_poverty_gap": {"tf": 1.4142135623730951}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}}, "df": 3}}}}}}}}, "m": {"docs": {}, "df": 0, "a": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}}, "df": 1}}, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"src.data.read.get_asset_damage": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1.4142135623730951}}, "df": 2}}}}, "n": {"docs": {}, "df": 0, "d": {"docs": {"src.data.write.find_poor": {"tf": 1.4142135623730951}, "src.data.write.calculate_poverty_gap": {"tf": 1.7320508075688772}}, "df": 2}}, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "h": {"docs": {"src.data.write.get_people_by_years_in_poverty": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}}, "df": 3}}}, "q": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"src.modules.households.duplicate_households": {"tf": 1}}, "df": 1}}}}, "f": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}}, "df": 2}}}}}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.estimate_savings": {"tf": 1.4142135623730951}}, "df": 1, "d": {"docs": {"src.modules.households.estimate_savings": {"tf": 1}}, "df": 1}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.modules.households.estimate_savings": {"tf": 1}}, "df": 1}}}}}}}}}}, "w": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "k": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "h": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}}, "df": 1}}}}}}}}, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1.4142135623730951}, "src.data.prepare.add_is_rural_column": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}}, "df": 5}}}}}}, "e": {"docs": {"src.model.initialize_model": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 3, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {"src.modules.households.calculate_pml": {"tf": 1}}, "df": 1, "s": {"docs": {"src.modules.households.duplicate_households": {"tf": 1.4142135623730951}}, "df": 1}}}}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"src.modules.households.duplicate_households": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1.4142135623730951}, "src.modules.households.set_vulnerability": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}}, "df": 9}}}, "a": {"docs": {}, "df": 0, "s": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 2}}}, "p": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}}, "df": 1}}}, "y": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 2.23606797749979}}, "df": 2}}}}, "o": {"docs": {}, "df": 0, "r": {"1": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}, "2": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}, "docs": {"src.data.write.find_poor": {"tf": 2.23606797749979}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1.4142135623730951}, "src.data.write.calculate_poverty_gap": {"tf": 2}, "src.modules.households.apply_individual_policy": {"tf": 1.7320508075688772}}, "df": 4}}, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"src.data.write.find_poor": {"tf": 1.4142135623730951}, "src.data.write.get_people_by_years_in_poverty": {"tf": 2}, "src.data.write.calculate_poverty_gap": {"tf": 2.23606797749979}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1.7320508075688772}}, "df": 5}}}}}, "p": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.modules.households.calculate_pml": {"tf": 1}}, "df": 1}}}}}}}}}, "d": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1.4142135623730951}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1.4142135623730951}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.4142135623730951}, "src.modules.households.calculate_pml": {"tf": 1.4142135623730951}, "src.modules.households.estimate_savings": {"tf": 1.4142135623730951}, "src.modules.households.set_vulnerability": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}}, "df": 19}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.prepare.prepare_household_survey": {"tf": 1}}, "df": 2}}}}, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"src.data.prepare.linear_regression": {"tf": 1}}, "df": 1}}}}}}}, "o": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.data.prepare.start_pipeline": {"tf": 1}}, "df": 1}}}}}}}, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}}, "df": 2, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"src.data.write.get_outcomes": {"tf": 1.4142135623730951}, "src.modules.households.calculate_average_productivity": {"tf": 1.7320508075688772}, "src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}}, "df": 3}}}}}}}}}, "b": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1}}, "df": 3}}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"src.modules.households.determine_affected": {"tf": 1}}, "df": 1}}}}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"src.data.read.get_asset_damage": {"tf": 1.4142135623730951}, "src.modules.households.calculate_average_productivity": {"tf": 1.4142135623730951}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.4142135623730951}, "src.modules.households.calculate_pml": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}}, "df": 5}}}}, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"src.data.prepare.prepare_household_survey": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 4}}}}}, "s": {"docs": {"src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 3}}}}}, "i": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.start_pipeline": {"tf": 1}}, "df": 1}}}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {"src.data.read.get_asset_damage": {"tf": 1.4142135623730951}}, "df": 1}}}, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write.calculate_average_annual_consumption_loss": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}}, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write.get_people_by_years_in_poverty": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "m": {"docs": {}, "df": 0, "l": {"docs": {"src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 2}}}, "b": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1.4142135623730951}, "src.data.read.get_asset_damage": {"tf": 1}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}}, "df": 7}}}, "e": {"docs": {"src.data.prepare.rename_assets_column": {"tf": 1}, "src.model.initialize_model": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 5, "g": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.data.write.find_poor": {"tf": 1.4142135623730951}, "src.data.write.calculate_poverty_gap": {"tf": 1.7320508075688772}}, "df": 2}}}}}}}, "t": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 1}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.modules.households.determine_affected": {"tf": 1}}, "df": 1}}}}, "y": {"docs": {"src.model.initialize_model": {"tf": 1}}, "df": 1}, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 2}}}}, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "s": {"docs": {"src.modules.households.calculate_exposure": {"tf": 1.7320508075688772}}, "df": 1}}}, "u": {"docs": {}, "df": 0, "t": {"docs": {"src.modules.households.determine_affected": {"tf": 1}}, "df": 1}}}, "v": {"docs": {"src.modules.households.set_vulnerability": {"tf": 1}}, "df": 1, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1.4142135623730951}, "src.data.prepare.linear_regression": {"tf": 1}}, "df": 2}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1.4142135623730951}, "src.data.read.read_household_survey": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1.4142135623730951}}, "df": 6}}}}}}}}}, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"src.modules.households.set_vulnerability": {"tf": 2.23606797749979}, "src.modules.households.calculate_exposure": {"tf": 1}}, "df": 2}}}}}}}}}}}}}, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}}, "df": 1}}}, "y": {"docs": {"src.data.analyse.prepare_outcomes": {"tf": 1}}, "df": 1}}}}}}}}}, "i": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {"src.modules.households.set_vulnerability": {"tf": 1}}, "df": 1}}}}}}, "p": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1.4142135623730951}}, "df": 1}, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"src.modules.optimize.run_optimization": {"tf": 1}}, "df": 1}}}}}}}, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "l": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}}, "df": 1}}}, "s": {"docs": {}, "df": 0, "s": {"docs": {"src.modules.households.duplicate_households": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 2}}}, "o": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {"src.data.prepare.load_data": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}}, "df": 2}}, "s": {"docs": {}, "df": 0, "s": {"docs": {"src.data.read.get_asset_damage": {"tf": 1.4142135623730951}, "src.data.write.get_outcomes": {"tf": 1.4142135623730951}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 2.23606797749979}, "src.data.write.calculate_resilience": {"tf": 1.4142135623730951}, "src.modules.households.calculate_pml": {"tf": 2.23606797749979}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 7}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write.find_poor": {"tf": 1.4142135623730951}, "src.data.write.calculate_poverty_gap": {"tf": 1.4142135623730951}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 2}}, "df": 3, "a": {"docs": {}, "df": 0, "r": {"docs": {"src.data.prepare.linear_regression": {"tf": 1}}, "df": 1}}}}}, "u": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {"src.data.read.read_household_survey": {"tf": 1}}, "df": 1}}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 1}}}}}}, "s": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}}, "df": 1}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.modules.households.estimate_savings": {"tf": 1.7320508075688772}}, "df": 1, "s": {"docs": {"src.modules.households.estimate_savings": {"tf": 2.23606797749979}}, "df": 1}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"src.data.read.read_household_survey": {"tf": 1}}, "df": 1}}}, "m": {"docs": {}, "df": 0, "e": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 2}, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"src.model.initialize_model": {"tf": 1}}, "df": 1}}}}}, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}, "src.data.write.find_poor": {"tf": 2}, "src.data.write.calculate_poverty_gap": {"tf": 2}}, "df": 4}}}}}}}}, "n": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}}}}}, "t": {"docs": {}, "df": 0, "r": {"docs": {"src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1.4142135623730951}, "src.data.read.read_household_survey": {"tf": 1}, "src.model.initialize_model": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 5, "u": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}}}}, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.start_pipeline": {"tf": 1}}, "df": 1}}, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "s": {"docs": {"src.data.read.get_asset_damage": {"tf": 1.4142135623730951}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.4142135623730951}, "src.modules.households.calculate_pml": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}}, "df": 5}}}}}}}}, "o": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "k": {"docs": {"src.data.read.get_asset_damage": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1.4142135623730951}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.4142135623730951}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}}, "df": 5}}}}, "u": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}}, "df": 3}}}}}}}, "b": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.subset_columns": {"tf": 1}}, "df": 1}}}}, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "y": {"docs": {"src.data.read.read_household_survey": {"tf": 1.4142135623730951}, "src.model.initialize_model": {"tf": 1.4142135623730951}, "src.modules.households.duplicate_households": {"tf": 1.7320508075688772}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1.7320508075688772}, "src.modules.households.calculate_pml": {"tf": 1.4142135623730951}, "src.modules.households.estimate_savings": {"tf": 1.4142135623730951}, "src.modules.households.set_vulnerability": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1.4142135623730951}, "src.modules.households.apply_individual_policy": {"tf": 1.4142135623730951}}, "df": 11}}}}}, "e": {"docs": {}, "df": 0, "t": {"docs": {"src.data.prepare.rename_other_columns": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}}, "df": 2}, "e": {"docs": {"src.data.prepare.rename_other_columns": {"tf": 1}}, "df": 1}, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"src.modules.households.select_district": {"tf": 1}}, "df": 1}}}}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.linear_regression": {"tf": 1}}, "df": 1}}}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"src.data.read.get_asset_damage": {"tf": 1.7320508075688772}}, "df": 1}}}}, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {"src.data.read.get_asset_damage": {"tf": 1}, "src.modules.households.select_district": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}, "src.modules.households.calculate_exposure": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}, "src.modules.households.apply_individual_policy": {"tf": 1.4142135623730951}}, "df": 7}}}}}}}}, "x": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "x": {"docs": {"src.data.prepare.prepare_asset_damage": {"tf": 1}, "src.data.read.read_asset_damage": {"tf": 1}}, "df": 2}}}}, "m": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "l": {"docs": {"src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.write.get_outcomes": {"tf": 1}, "src.model.initialize_model": {"tf": 1}, "src.model.run_model": {"tf": 1}}, "df": 4}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {"src.data.prepare.rename_assets_column": {"tf": 1}}, "df": 1}}}, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "y": {"docs": {"src.data.prepare.add_missing_columns": {"tf": 1}}, "df": 1}}}}}}, "x": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {"src.data.write.calculate_resilience": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1}}, "df": 3}}}}}, "t": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "h": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 1}}}, "s": {"docs": {}, "df": 0, "k": {"docs": {"src.modules.households.determine_affected": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.data.prepare.add_missing_columns": {"tf": 1}}, "df": 1}}}}, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "h": {"docs": {"src.modules.households.adjust_assets_and_expenditure": {"tf": 1}}, "df": 1}}}}}}, "n": {"docs": {"src.model.initialize_model": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1.4142135623730951}}, "df": 2, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {"src.model.initialize_model": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1}}, "df": 2}}}}}}, "e": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"src.data.read.read_asset_damage": {"tf": 1}}, "df": 1}}}}}, "y": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1}}, "df": 1}}, "n": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.modules.optimize.run_optimization": {"tf": 1}}, "df": 4, "o": {"docs": {"src.modules.households.determine_affected": {"tf": 1}}, "df": 1, "t": {"docs": {"src.data.prepare.prepare_household_survey": {"tf": 1}, "src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.read.get_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}}, "df": 6}, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.estimate_savings": {"tf": 1}, "src.modules.households.set_vulnerability": {"tf": 1}}, "df": 2}}}}, "e": {"docs": {}, "df": 0, "w": {"docs": {"src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.prepare.add_housing_attributes": {"tf": 1}, "src.data.write.find_poor": {"tf": 1.4142135623730951}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1.4142135623730951}, "src.data.write.calculate_poverty_gap": {"tf": 1.4142135623730951}}, "df": 5}, "e": {"docs": {}, "df": 0, "d": {"docs": {"src.model.initialize_model": {"tf": 1}}, "df": 1}}, "a": {"docs": {}, "df": 0, "r": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1.4142135623730951}}, "df": 1}}}, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"src.data.read.get_asset_damage": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1}, "src.model.initialize_model": {"tf": 1}}, "df": 3}}}, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"src.data.write.get_outcomes": {"tf": 1}, "src.data.write.find_poor": {"tf": 1.4142135623730951}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1.4142135623730951}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}, "src.model.initialize_model": {"tf": 1}, "src.modules.households.duplicate_households": {"tf": 1.4142135623730951}, "src.modules.optimize.run_optimization": {"tf": 1}}, "df": 9}}}}}}, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"src.modules.households.calculate_average_productivity": {"tf": 1}}, "df": 1, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "d": {"docs": {"src.data.prepare.add_is_rural_column": {"tf": 1}, "src.data.read.read_household_survey": {"tf": 1.4142135623730951}, "src.data.write.find_poor": {"tf": 1}, "src.model.initialize_model": {"tf": 1.4142135623730951}, "src.modules.households.duplicate_households": {"tf": 1.7320508075688772}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 2}, "src.modules.households.calculate_pml": {"tf": 1.4142135623730951}, "src.modules.households.estimate_savings": {"tf": 1.4142135623730951}, "src.modules.households.set_vulnerability": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 1.7320508075688772}, "src.modules.households.apply_individual_policy": {"tf": 1.4142135623730951}, "src.modules.optimize.run_optimization": {"tf": 1}}, "df": 14, "s": {"docs": {"src.data.write.add_columns": {"tf": 1.4142135623730951}, "src.data.write.get_outcomes": {"tf": 1.4142135623730951}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1.4142135623730951}, "src.data.write.calculate_resilience": {"tf": 1.7320508075688772}, "src.model.initialize_model": {"tf": 1.4142135623730951}, "src.modules.households.duplicate_households": {"tf": 2.449489742783178}, "src.modules.households.calculate_average_productivity": {"tf": 1}, "src.modules.households.adjust_assets_and_expenditure": {"tf": 1}, "src.modules.households.calculate_pml": {"tf": 1}, "src.modules.households.select_district": {"tf": 1}, "src.modules.households.estimate_savings": {"tf": 1.4142135623730951}, "src.modules.households.set_vulnerability": {"tf": 1.4142135623730951}, "src.modules.households.calculate_exposure": {"tf": 1.4142135623730951}, "src.modules.households.determine_affected": {"tf": 2.23606797749979}, "src.modules.households.apply_individual_policy": {"tf": 1.4142135623730951}, "src.modules.optimize.run_optimization": {"tf": 1.7320508075688772}}, "df": 17}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"src.data.prepare.decode_housing_attributes": {"tf": 1}, "src.data.prepare.add_housing_attributes": {"tf": 1}}, "df": 2}}}}}}, "a": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"src.model.initialize_model": {"tf": 1}, "src.modules.households.determine_affected": {"tf": 1}}, "df": 2}}}}, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"src.data.read.get_asset_damage": {"tf": 1}, "src.data.write.find_poor": {"tf": 1}, "src.data.write.get_people_by_years_in_poverty": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}}, "df": 4}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"src.data.read.get_asset_damage": {"tf": 1}, "src.data.write.calculate_poverty_gap": {"tf": 1}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1}, "src.data.write.calculate_resilience": {"tf": 1}}, "df": 4}}}}}, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "p": {"docs": {"src.modules.households.apply_individual_policy": {"tf": 1.7320508075688772}}, "df": 1}}}}, "a": {"docs": {}, "df": 0, "p": {"docs": {"src.data.write.calculate_poverty_gap": {"tf": 1.7320508075688772}}, "df": 1}, "u": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {"src.modules.households.estimate_savings": {"tf": 1}}, "df": 1}}}}}}}}, "y": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {"src.data.write.get_people_by_years_in_poverty": {"tf": 1.4142135623730951}}, "df": 1, "s": {"docs": {"src.data.write.get_outcomes": {"tf": 1.4142135623730951}, "src.data.write.calculate_poverty_gap": {"tf": 1.4142135623730951}, "src.data.write.calculate_average_annual_consumption_loss": {"tf": 1.4142135623730951}, "src.modules.optimize.run_optimization": {"tf": 1.4142135623730951}}, "df": 4}}}}}, "k": {"docs": {"src.modules.households.calculate_average_productivity": {"tf": 1}}, "df": 1}}}}, "pipeline": ["trimmer"], "_isPrebuiltIndex": true};
-
- // mirrored in build-search-index.js (part 1)
- // Also split on html tags. this is a cheap heuristic, but good enough.
- elasticlunr.tokenizer.setSeperator(/[\s\-.;&_'"=,()]+|<[^>]*>/);
-
- let searchIndex;
- if (docs._isPrebuiltIndex) {
- console.info("using precompiled search index");
- searchIndex = elasticlunr.Index.load(docs);
- } else {
- console.time("building search index");
- // mirrored in build-search-index.js (part 2)
- searchIndex = elasticlunr(function () {
- this.pipeline.remove(elasticlunr.stemmer);
- this.pipeline.remove(elasticlunr.stopWordFilter);
- this.addField("qualname");
- this.addField("fullname");
- this.addField("annotation");
- this.addField("default_value");
- this.addField("signature");
- this.addField("bases");
- this.addField("doc");
- this.setRef("fullname");
- });
- for (let doc of docs) {
- searchIndex.addDoc(doc);
- }
- console.timeEnd("building search index");
- }
-
- return (term) => searchIndex.search(term, {
- fields: {
- qualname: {boost: 4},
- fullname: {boost: 2},
- annotation: {boost: 2},
- default_value: {boost: 2},
- signature: {boost: 2},
- bases: {boost: 2},
- doc: {boost: 1},
- },
- expand: true
- });
-})();
\ No newline at end of file
diff --git a/docs/src.html b/docs/src.html
deleted file mode 100644
index 3383478..0000000
--- a/docs/src.html
+++ /dev/null
@@ -1,234 +0,0 @@
-
-
-
-
-
-
- src API documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/src/data.html b/docs/src/data.html
deleted file mode 100644
index 4a0147f..0000000
--- a/docs/src/data.html
+++ /dev/null
@@ -1,241 +0,0 @@
-
-
-
-
-
-
- src.data API documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/src/data/analyse.html b/docs/src/data/analyse.html
deleted file mode 100644
index d01c32f..0000000
--- a/docs/src/data/analyse.html
+++ /dev/null
@@ -1,876 +0,0 @@
-
-
-
-
-
-
- src.data.analyse API documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- View Source
-
- 1 # Prepare the results of the experiments for the analysis.
- 2
- 3 import pandas as pd
- 4 import numpy as np
- 5 import ast
- 6 import geopandas as gpd
- 7 from ema_workbench import load_results
- 8
- 9
- 10 def prepare_outcomes ( results : tuple , add_policies : bool , add_uncertainties : bool ) -> pd . DataFrame :
- 11 '''Convert outcomes dict into a data frame.
- 12
- 13 Args:
- 14 results (tuple): The results of the experiments in the EMA Workbench format.
- 15 add_policies (bool): Whether to add policy values to the data frame.
- 16 add_uncertainties (bool): Whether to add uncertainty values to the data frame.
- 17
- 18 Returns:
- 19 pd.DataFrame: Outcomes data frame.
- 20 '''
- 21 # * Note that we specify all outcomes in `get_outcomes` function in `write.py`
- 22 # * Here we just read them in the same sequence that they are written
- 23 outcome_names = [
- 24 'total_population' ,
- 25 'total_asset_loss' ,
- 26 'total_consumption_loss' ,
- 27 'event_damage' ,
- 28 'total_asset_stock' ,
- 29 'average_productivity' ,
- 30 'total_asset_in_survey' ,
- 31 'expected_loss_fraction' ,
- 32 'n_affected_people' ,
- 33 'annual_average_consumption' ,
- 34 'poverty_line_adjusted' ,
- 35 'pml' ,
- 36 'n_poor_initial' ,
- 37 'n_poor_affected' ,
- 38 'n_new_poor' ,
- 39 'initial_poverty_gap' ,
- 40 'new_poverty_gap' ,
- 41 'annual_average_consumption_loss' ,
- 42 'annual_average_consumption_loss_pct' ,
- 43 'r' ,
- 44 'recovery_rate' ,
- 45 'years_in_poverty' ,
- 46 ]
- 47
- 48 uncertainty_names = [ 'consumption_utility' ,
- 49 'discount_rate' ,
- 50 'income_and_expenditure_growth' ,
- 51 'poverty_bias' ]
- 52
- 53 experiments , _ = results
- 54 experiments [ 'random_seed' ] = experiments [ 'random_seed' ] . astype ( int )
- 55 experiments [ 'scenario' ] = experiments [ 'scenario' ] . astype ( int )
- 56 if len ( experiments [ 'random_seed' ] . unique ()) != experiments [ 'scenario' ] . max () - experiments [ 'scenario' ] . min () + 1 :
- 57 # print(experiments['random_seed'].value_counts())
- 58 print ( 'WARNING! Random seeds are not unique.' )
- 59 # raise ValueError('Random seeds are not unique')
- 60
- 61 policy_names = [ 'my_policy' ]
- 62
- 63 if add_policies :
- 64 if add_uncertainties :
- 65 columns = [ 'scenario' , 'policy' , 'district' , 'random_seed' ] + \
- 66 policy_names + uncertainty_names + outcome_names
- 67 else :
- 68 columns = [ 'scenario' , 'policy' , 'district' , 'random_seed' ] + \
- 69 policy_names + outcome_names
- 70 else :
- 71 if add_uncertainties :
- 72 columns = [ 'scenario' , 'policy' , 'district' , 'random_seed' ] + \
- 73 uncertainty_names + outcome_names
- 74 else :
- 75 columns = [ 'scenario' , 'policy' , 'district' ,
- 76 'random_seed' ] + outcome_names
- 77
- 78 scenarios = results [ 0 ][ 'scenario' ] . values
- 79 n_scenarios = results [ 0 ][ 'scenario' ] . unique () . size
- 80 policies = results [ 0 ][ 'policy' ] . values
- 81 random_seeds = results [ 0 ][ 'random_seed' ] . values
- 82 n_policies = results [ 0 ][ 'policy' ] . unique () . size
- 83 n_districts = len ( results [ 1 ] . keys ())
- 84
- 85 if add_policies :
- 86 policy_values = results [ 0 ][ policy_names ] . values
- 87
- 88 if add_uncertainties :
- 89 uncertainty_values = results [ 0 ][ uncertainty_names ] . values
- 90
- 91 n_columns = len ( columns )
- 92 n_rows = n_scenarios * n_policies * n_districts
- 93 outcomes = np . zeros (( n_rows , n_columns ), dtype = object )
- 94
- 95 i = 0 # To iterate over rows = scenarios * policies * districts
- 96 for district , district_outcomes in results [ 1 ] . items ():
- 97 # To iterate over rows = scenarios * policies (experiments dataframe)
- 98 k = 0
- 99 # We reset k every time we change district
-100 for arr in district_outcomes :
-101 # The first 3 rows for scenario, policy and district
-102 outcomes [ i , 0 ] = scenarios [ k ]
-103 outcomes [ i , 1 ] = policies [ k ]
-104 outcomes [ i , 2 ] = district
-105 outcomes [ i , 3 ] = random_seeds [ k ]
-106
-107 if add_policies :
-108 if add_uncertainties :
-109 # Add policy values
-110 # From 4 to 4 + len(policy_names) policy values
-111 for j , name in enumerate ( policy_names ):
-112 outcomes [ i , 4 + j ] = policy_values [ k , j ]
-113
-114 # Add uncertainty values
-115 # From 4 + len(policy_names) to 4 + len(policy_names) + len(uncertainty_names) uncertainty values
-116 for j , name in enumerate ( uncertainty_names ):
-117 outcomes [ i , 4 + len ( policy_names ) + j ] = uncertainty_values [ k , j ]
-118
-119 # Add outcomes
-120 # From 4 + len(policy_names) + len(uncertainty_names) to 4 + len(policy_names) + len(uncertainty_names) + len(outcome_names) outcomes
-121 l = 4 + len ( policy_names ) + len ( uncertainty_names )
-122 for v , name in zip ( arr , outcome_names ):
-123 if name == 'years_in_poverty' :
-124 outcomes [ i , l ] = ast . literal_eval ( v )
-125 else :
-126 outcomes [ i , l ] = v
-127 l += 1
-128 else :
-129 # Add policy values
-130 # From 4 to 4 + len(policy_names) policy values
-131 for j , name in enumerate ( policy_names ):
-132 outcomes [ i , 4 + j ] = policy_values [ k , j ]
-133
-134 # Add outcomes
-135 # From 4 + len(policy_names) to 4 + len(policy_names) + len(outcome_names) outcomes
-136 l = 4 + len ( policy_names )
-137 for v , name in zip ( arr , outcome_names ):
-138 if name == 'years_in_poverty' :
-139 outcomes [ i , l ] = ast . literal_eval ( v )
-140 else :
-141 outcomes [ i , l ] = v
-142 l += 1
-143 else :
-144 if add_uncertainties :
-145 # Add uncertainty values
-146 # From 4 to 4 + len(uncertainty_names) uncertainty values
-147 for j , name in enumerate ( uncertainty_names ):
-148 outcomes [ i , 4 + j ] = uncertainty_values [ k , j ]
-149
-150 # Add outcomes
-151 # From 4 + len(uncertainty_names) to 4 + len(uncertainty_names) + len(outcome_names) outcomes
-152 l = 4 + len ( uncertainty_names )
-153 for v , name in zip ( arr , outcome_names ):
-154 if name == 'years_in_poverty' :
-155 outcomes [ i , l ] = ast . literal_eval ( v )
-156 else :
-157 outcomes [ i , l ] = v
-158 l += 1
-159 else :
-160 # Add outcomes
-161 # From 4 to 4 + len(outcome_names) outcomes
-162 l = 4
-163 for v , name in zip ( arr , outcome_names ):
-164 if name == 'years_in_poverty' :
-165 outcomes [ i , l ] = ast . literal_eval ( v )
-166 else :
-167 outcomes [ i , l ] = v
-168 l += 1
-169 k += 1 # increase row index to get next experiment for the current district
-170 i += 1 # increase row index of the outcomes dataframe
-171 outcomes = pd . DataFrame ( outcomes , columns = columns )
-172
-173 # Convert numeric columns to numeric
-174 if add_policies :
-175 numeric_columns = outcomes . columns [ 5 : - 1 ] . tolist ()
-176 outcomes [ numeric_columns ] = outcomes [ numeric_columns ] . apply (
-177 pd . to_numeric )
-178 else :
-179 numeric_columns = outcomes . columns [ 4 : - 1 ] . tolist ()
-180 outcomes [ numeric_columns ] = outcomes [ numeric_columns ] . apply (
-181 pd . to_numeric )
-182
-183 # Rename a district
-184 outcomes [ 'district' ] . replace (
-185 { 'AnseLaRayeCanaries' : 'Anse-La-Raye & Canaries' }, inplace = True )
-186
-187 # Convert pct columns to percentage
-188 outcomes [ 'annual_average_consumption_loss_pct' ] = outcomes [ 'annual_average_consumption_loss_pct' ] * 100
-189 outcomes [ 'initial_poverty_gap' ] = outcomes [ 'initial_poverty_gap' ] * 100
-190 outcomes [ 'new_poverty_gap' ] = outcomes [ 'new_poverty_gap' ] * 100
-191
-192 # Calculate the percentage of new poor
-193 outcomes = outcomes . assign ( n_new_poor_increase_pct = outcomes [ 'n_new_poor' ] . div (
-194 outcomes [ 'total_population' ]) . multiply ( 100 ))
-195
-196 # outcomes['pct_poor_before'] = outcomes['n_poor_initial'].div(
-197 # outcomes['total_population'])
-198 # outcomes['pct_poor_after'] = outcomes['n_new_poor'].add(
-199 # outcomes['n_poor_initial']).div(outcomes['total_population'])
-200 # outcomes['pct_poor_increase'] = outcomes['pct_poor_after'].sub(
-201 # outcomes['pct_poor_before'])
-202
-203 # Move years_in_poverty column to the end of the data frame
-204 outcomes = outcomes [[ c for c in outcomes if c not in [
-205 'years_in_poverty' ]] + [ 'years_in_poverty' ]]
-206
-207 return outcomes
-208
-209
-210 def get_spatial_outcomes ( outcomes : pd . DataFrame , outcomes_of_interest : list = [], country : str = 'Saint Lucia' , aggregation : str = 'mean' ) -> gpd . GeoDataFrame :
-211 # Load country shapefile
-212 country = 'Saint Lucia'
-213 gdf = gpd . read_file (
-214 f '../data/raw/shapefiles/ { country } /gadm36_LCA_shp/gadm36_LCA_1.shp' )
-215
-216 # Align district names with the ones in the outcomes
-217 gdf [ 'NAME_1' ] . replace (
-218 { 'Soufrière' : 'Soufriere' , 'Vieux Fort' : 'Vieuxfort' }, inplace = True )
-219
-220 # Merge Anse-la-Raye and Canaries into a single geometry
-221 geometry = gdf [ gdf [ 'NAME_1' ] . isin (
-222 [ 'Anse-la-Raye' , 'Canaries' ])] . unary_union
-223
-224 # Add it to the dataframe
-225 gdf . loc [ len ( gdf )] = [ None , None , 'LCA.11_1' , 'Anse-La-Raye & Canaries' ,
-226 None , None , None , None , None , None , geometry ]
-227 gdf = gdf [ gdf [ 'NAME_1' ] . isin ( outcomes [ 'district' ] . unique ())]
-228
-229 if len ( outcomes_of_interest ) == 0 :
-230 outcomes_of_interest = [ 'total_asset_loss' ,
-231 'total_consumption_loss' ,
-232 'n_affected_people' ,
-233 'n_new_poor' ,
-234 'new_poverty_gap' ,
-235 'annual_average_consumption_loss' ,
-236 'annual_average_consumption_loss_pct' ,
-237 'n_new_poor_increase_pct' ,
-238 'r' ]
-239
-240 # Aggregate outcomes
-241 if aggregation == 'mean' :
-242 aggregated = outcomes [[ 'district' ] +
-243 outcomes_of_interest ] . groupby ( 'district' ) . mean ()
-244 elif aggregation == 'median' :
-245 aggregated = outcomes [[ 'district' ] +
-246 outcomes_of_interest ] . groupby ( 'district' ) . median ()
-247 else :
-248 raise ValueError ( 'Aggregation must be either mean or median' )
-249
-250 # Merge with the shapefile
-251 gdf = pd . merge ( gdf , aggregated , left_on = 'NAME_1' , right_index = True )
-252 gdf . reset_index ( inplace = True , drop = True )
-253 return gdf
-254
-255
-256 def get_policy_effectiveness_tab ( outcomes : pd . DataFrame ) -> pd . DataFrame :
-257 policy_name_mapper = { 'all+0' : 'None' ,
-258 'all+10' : '10% to all' ,
-259 'all+30' : '30% to all' ,
-260 'all+50' : '50% to all' ,
-261 'all+100' : '100% to all' ,
-262 'poor+0' : 'None' ,
-263 'poor+10' : '10% to poor' ,
-264 'poor+30' : '30% to poor' ,
-265 'poor+50' : '50% to poor' ,
-266 'poor+100' : '100% to poor' ,
-267 'poor_near_poor1.25+0' : 'None' ,
-268 'poor_near_poor1.25+10' : '10% to poor and near poor (1.25)' ,
-269 'poor_near_poor1.25+30' : '30% to poor and near poor (1.25)' ,
-270 'poor_near_poor1.25+50' : '50% to poor and near poor (1.25)' ,
-271 'poor_near_poor1.25+100' : '100% to poor and near poor (1.25)' ,
-272 'poor_near_poor2.0+0' : 'None' ,
-273 'poor_near_poor2.0+10' : '10% to poor and near poor (2.0)' ,
-274 'poor_near_poor2.0+30' : '30% to poor and near poor (2.0)' ,
-275 'poor_near_poor2.0+50' : '50% to poor and near poor (2.0)' ,
-276 'poor_near_poor2.0+100' : '100% to poor and near poor (2.0)' }
-277 df = outcomes . copy ()
-278 df [ 'my_policy' ] = df [ 'my_policy' ] . replace ( policy_name_mapper )
-279 df [ 'my_policy' ] = pd . Categorical ( df [ 'my_policy' ], categories = [ 'None' , '10% to all' , '30% to all' , '50% to all' , '100% to all' ,
-280 '10% to poor' , '30% to poor' , '50% to poor' , '100% to poor' ,
-281 '10% to poor and near poor (1.25)' , '30% to poor and near poor (1.25)' , '50% to poor and near poor (1.25)' , '100% to poor and near poor (1.25)' ,
-282 '10% to poor and near poor (2.0)' , '30% to poor and near poor (2.0)' , '50% to poor and near poor (2.0)' , '100% to poor and near poor (2.0)' ], ordered = True )
-283 df . rename ( columns = { 'my_policy' : 'Policy' ,
-284 'district' : 'District' }, inplace = True )
-285 df . rename ( columns = { 'annual_average_consumption_loss_pct' : 'Annual average consumption loss (%)' ,
-286 'n_new_poor' : 'Number of new poor' },
-287 inplace = True )
-288 df [ 'Policy ID' ] = df [ 'Policy' ] . cat . codes
-289 return df
-
-
-
-
-
-
-
-
- def
- prepare_outcomes ( results : tuple , add_policies : bool , add_uncertainties : bool ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 11 def prepare_outcomes ( results : tuple , add_policies : bool , add_uncertainties : bool ) -> pd . DataFrame :
- 12 '''Convert outcomes dict into a data frame.
- 13
- 14 Args:
- 15 results (tuple): The results of the experiments in the EMA Workbench format.
- 16 add_policies (bool): Whether to add policy values to the data frame.
- 17 add_uncertainties (bool): Whether to add uncertainty values to the data frame.
- 18
- 19 Returns:
- 20 pd.DataFrame: Outcomes data frame.
- 21 '''
- 22 # * Note that we specify all outcomes in `get_outcomes` function in `write.py`
- 23 # * Here we just read them in the same sequence that they are written
- 24 outcome_names = [
- 25 'total_population' ,
- 26 'total_asset_loss' ,
- 27 'total_consumption_loss' ,
- 28 'event_damage' ,
- 29 'total_asset_stock' ,
- 30 'average_productivity' ,
- 31 'total_asset_in_survey' ,
- 32 'expected_loss_fraction' ,
- 33 'n_affected_people' ,
- 34 'annual_average_consumption' ,
- 35 'poverty_line_adjusted' ,
- 36 'pml' ,
- 37 'n_poor_initial' ,
- 38 'n_poor_affected' ,
- 39 'n_new_poor' ,
- 40 'initial_poverty_gap' ,
- 41 'new_poverty_gap' ,
- 42 'annual_average_consumption_loss' ,
- 43 'annual_average_consumption_loss_pct' ,
- 44 'r' ,
- 45 'recovery_rate' ,
- 46 'years_in_poverty' ,
- 47 ]
- 48
- 49 uncertainty_names = [ 'consumption_utility' ,
- 50 'discount_rate' ,
- 51 'income_and_expenditure_growth' ,
- 52 'poverty_bias' ]
- 53
- 54 experiments , _ = results
- 55 experiments [ 'random_seed' ] = experiments [ 'random_seed' ] . astype ( int )
- 56 experiments [ 'scenario' ] = experiments [ 'scenario' ] . astype ( int )
- 57 if len ( experiments [ 'random_seed' ] . unique ()) != experiments [ 'scenario' ] . max () - experiments [ 'scenario' ] . min () + 1 :
- 58 # print(experiments['random_seed'].value_counts())
- 59 print ( 'WARNING! Random seeds are not unique.' )
- 60 # raise ValueError('Random seeds are not unique')
- 61
- 62 policy_names = [ 'my_policy' ]
- 63
- 64 if add_policies :
- 65 if add_uncertainties :
- 66 columns = [ 'scenario' , 'policy' , 'district' , 'random_seed' ] + \
- 67 policy_names + uncertainty_names + outcome_names
- 68 else :
- 69 columns = [ 'scenario' , 'policy' , 'district' , 'random_seed' ] + \
- 70 policy_names + outcome_names
- 71 else :
- 72 if add_uncertainties :
- 73 columns = [ 'scenario' , 'policy' , 'district' , 'random_seed' ] + \
- 74 uncertainty_names + outcome_names
- 75 else :
- 76 columns = [ 'scenario' , 'policy' , 'district' ,
- 77 'random_seed' ] + outcome_names
- 78
- 79 scenarios = results [ 0 ][ 'scenario' ] . values
- 80 n_scenarios = results [ 0 ][ 'scenario' ] . unique () . size
- 81 policies = results [ 0 ][ 'policy' ] . values
- 82 random_seeds = results [ 0 ][ 'random_seed' ] . values
- 83 n_policies = results [ 0 ][ 'policy' ] . unique () . size
- 84 n_districts = len ( results [ 1 ] . keys ())
- 85
- 86 if add_policies :
- 87 policy_values = results [ 0 ][ policy_names ] . values
- 88
- 89 if add_uncertainties :
- 90 uncertainty_values = results [ 0 ][ uncertainty_names ] . values
- 91
- 92 n_columns = len ( columns )
- 93 n_rows = n_scenarios * n_policies * n_districts
- 94 outcomes = np . zeros (( n_rows , n_columns ), dtype = object )
- 95
- 96 i = 0 # To iterate over rows = scenarios * policies * districts
- 97 for district , district_outcomes in results [ 1 ] . items ():
- 98 # To iterate over rows = scenarios * policies (experiments dataframe)
- 99 k = 0
-100 # We reset k every time we change district
-101 for arr in district_outcomes :
-102 # The first 3 rows for scenario, policy and district
-103 outcomes [ i , 0 ] = scenarios [ k ]
-104 outcomes [ i , 1 ] = policies [ k ]
-105 outcomes [ i , 2 ] = district
-106 outcomes [ i , 3 ] = random_seeds [ k ]
-107
-108 if add_policies :
-109 if add_uncertainties :
-110 # Add policy values
-111 # From 4 to 4 + len(policy_names) policy values
-112 for j , name in enumerate ( policy_names ):
-113 outcomes [ i , 4 + j ] = policy_values [ k , j ]
-114
-115 # Add uncertainty values
-116 # From 4 + len(policy_names) to 4 + len(policy_names) + len(uncertainty_names) uncertainty values
-117 for j , name in enumerate ( uncertainty_names ):
-118 outcomes [ i , 4 + len ( policy_names ) + j ] = uncertainty_values [ k , j ]
-119
-120 # Add outcomes
-121 # From 4 + len(policy_names) + len(uncertainty_names) to 4 + len(policy_names) + len(uncertainty_names) + len(outcome_names) outcomes
-122 l = 4 + len ( policy_names ) + len ( uncertainty_names )
-123 for v , name in zip ( arr , outcome_names ):
-124 if name == 'years_in_poverty' :
-125 outcomes [ i , l ] = ast . literal_eval ( v )
-126 else :
-127 outcomes [ i , l ] = v
-128 l += 1
-129 else :
-130 # Add policy values
-131 # From 4 to 4 + len(policy_names) policy values
-132 for j , name in enumerate ( policy_names ):
-133 outcomes [ i , 4 + j ] = policy_values [ k , j ]
-134
-135 # Add outcomes
-136 # From 4 + len(policy_names) to 4 + len(policy_names) + len(outcome_names) outcomes
-137 l = 4 + len ( policy_names )
-138 for v , name in zip ( arr , outcome_names ):
-139 if name == 'years_in_poverty' :
-140 outcomes [ i , l ] = ast . literal_eval ( v )
-141 else :
-142 outcomes [ i , l ] = v
-143 l += 1
-144 else :
-145 if add_uncertainties :
-146 # Add uncertainty values
-147 # From 4 to 4 + len(uncertainty_names) uncertainty values
-148 for j , name in enumerate ( uncertainty_names ):
-149 outcomes [ i , 4 + j ] = uncertainty_values [ k , j ]
-150
-151 # Add outcomes
-152 # From 4 + len(uncertainty_names) to 4 + len(uncertainty_names) + len(outcome_names) outcomes
-153 l = 4 + len ( uncertainty_names )
-154 for v , name in zip ( arr , outcome_names ):
-155 if name == 'years_in_poverty' :
-156 outcomes [ i , l ] = ast . literal_eval ( v )
-157 else :
-158 outcomes [ i , l ] = v
-159 l += 1
-160 else :
-161 # Add outcomes
-162 # From 4 to 4 + len(outcome_names) outcomes
-163 l = 4
-164 for v , name in zip ( arr , outcome_names ):
-165 if name == 'years_in_poverty' :
-166 outcomes [ i , l ] = ast . literal_eval ( v )
-167 else :
-168 outcomes [ i , l ] = v
-169 l += 1
-170 k += 1 # increase row index to get next experiment for the current district
-171 i += 1 # increase row index of the outcomes dataframe
-172 outcomes = pd . DataFrame ( outcomes , columns = columns )
-173
-174 # Convert numeric columns to numeric
-175 if add_policies :
-176 numeric_columns = outcomes . columns [ 5 : - 1 ] . tolist ()
-177 outcomes [ numeric_columns ] = outcomes [ numeric_columns ] . apply (
-178 pd . to_numeric )
-179 else :
-180 numeric_columns = outcomes . columns [ 4 : - 1 ] . tolist ()
-181 outcomes [ numeric_columns ] = outcomes [ numeric_columns ] . apply (
-182 pd . to_numeric )
-183
-184 # Rename a district
-185 outcomes [ 'district' ] . replace (
-186 { 'AnseLaRayeCanaries' : 'Anse-La-Raye & Canaries' }, inplace = True )
-187
-188 # Convert pct columns to percentage
-189 outcomes [ 'annual_average_consumption_loss_pct' ] = outcomes [ 'annual_average_consumption_loss_pct' ] * 100
-190 outcomes [ 'initial_poverty_gap' ] = outcomes [ 'initial_poverty_gap' ] * 100
-191 outcomes [ 'new_poverty_gap' ] = outcomes [ 'new_poverty_gap' ] * 100
-192
-193 # Calculate the percentage of new poor
-194 outcomes = outcomes . assign ( n_new_poor_increase_pct = outcomes [ 'n_new_poor' ] . div (
-195 outcomes [ 'total_population' ]) . multiply ( 100 ))
-196
-197 # outcomes['pct_poor_before'] = outcomes['n_poor_initial'].div(
-198 # outcomes['total_population'])
-199 # outcomes['pct_poor_after'] = outcomes['n_new_poor'].add(
-200 # outcomes['n_poor_initial']).div(outcomes['total_population'])
-201 # outcomes['pct_poor_increase'] = outcomes['pct_poor_after'].sub(
-202 # outcomes['pct_poor_before'])
-203
-204 # Move years_in_poverty column to the end of the data frame
-205 outcomes = outcomes [[ c for c in outcomes if c not in [
-206 'years_in_poverty' ]] + [ 'years_in_poverty' ]]
-207
-208 return outcomes
-
-
-
- Convert outcomes dict into a data frame.
-
-
Args:
- results (tuple): The results of the experiments in the EMA Workbench format.
- add_policies (bool): Whether to add policy values to the data frame.
- add_uncertainties (bool): Whether to add uncertainty values to the data frame.
-
-
Returns:
- pd.DataFrame: Outcomes data frame.
-
-
-
-
-
-
-
-
- def
- get_spatial_outcomes ( outcomes : pandas . core . frame . DataFrame , outcomes_of_interest : list = [] , country : str = 'Saint Lucia' , aggregation : str = 'mean' ) -> geopandas . geodataframe . GeoDataFrame :
-
- View Source
-
-
-
- 211 def get_spatial_outcomes ( outcomes : pd . DataFrame , outcomes_of_interest : list = [], country : str = 'Saint Lucia' , aggregation : str = 'mean' ) -> gpd . GeoDataFrame :
-212 # Load country shapefile
-213 country = 'Saint Lucia'
-214 gdf = gpd . read_file (
-215 f '../data/raw/shapefiles/ { country } /gadm36_LCA_shp/gadm36_LCA_1.shp' )
-216
-217 # Align district names with the ones in the outcomes
-218 gdf [ 'NAME_1' ] . replace (
-219 { 'Soufrière' : 'Soufriere' , 'Vieux Fort' : 'Vieuxfort' }, inplace = True )
-220
-221 # Merge Anse-la-Raye and Canaries into a single geometry
-222 geometry = gdf [ gdf [ 'NAME_1' ] . isin (
-223 [ 'Anse-la-Raye' , 'Canaries' ])] . unary_union
-224
-225 # Add it to the dataframe
-226 gdf . loc [ len ( gdf )] = [ None , None , 'LCA.11_1' , 'Anse-La-Raye & Canaries' ,
-227 None , None , None , None , None , None , geometry ]
-228 gdf = gdf [ gdf [ 'NAME_1' ] . isin ( outcomes [ 'district' ] . unique ())]
-229
-230 if len ( outcomes_of_interest ) == 0 :
-231 outcomes_of_interest = [ 'total_asset_loss' ,
-232 'total_consumption_loss' ,
-233 'n_affected_people' ,
-234 'n_new_poor' ,
-235 'new_poverty_gap' ,
-236 'annual_average_consumption_loss' ,
-237 'annual_average_consumption_loss_pct' ,
-238 'n_new_poor_increase_pct' ,
-239 'r' ]
-240
-241 # Aggregate outcomes
-242 if aggregation == 'mean' :
-243 aggregated = outcomes [[ 'district' ] +
-244 outcomes_of_interest ] . groupby ( 'district' ) . mean ()
-245 elif aggregation == 'median' :
-246 aggregated = outcomes [[ 'district' ] +
-247 outcomes_of_interest ] . groupby ( 'district' ) . median ()
-248 else :
-249 raise ValueError ( 'Aggregation must be either mean or median' )
-250
-251 # Merge with the shapefile
-252 gdf = pd . merge ( gdf , aggregated , left_on = 'NAME_1' , right_index = True )
-253 gdf . reset_index ( inplace = True , drop = True )
-254 return gdf
-
-
-
-
-
-
-
-
-
-
- def
- get_policy_effectiveness_tab (outcomes : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 257 def get_policy_effectiveness_tab ( outcomes : pd . DataFrame ) -> pd . DataFrame :
-258 policy_name_mapper = { 'all+0' : 'None' ,
-259 'all+10' : '10% to all' ,
-260 'all+30' : '30% to all' ,
-261 'all+50' : '50% to all' ,
-262 'all+100' : '100% to all' ,
-263 'poor+0' : 'None' ,
-264 'poor+10' : '10% to poor' ,
-265 'poor+30' : '30% to poor' ,
-266 'poor+50' : '50% to poor' ,
-267 'poor+100' : '100% to poor' ,
-268 'poor_near_poor1.25+0' : 'None' ,
-269 'poor_near_poor1.25+10' : '10% to poor and near poor (1.25)' ,
-270 'poor_near_poor1.25+30' : '30% to poor and near poor (1.25)' ,
-271 'poor_near_poor1.25+50' : '50% to poor and near poor (1.25)' ,
-272 'poor_near_poor1.25+100' : '100% to poor and near poor (1.25)' ,
-273 'poor_near_poor2.0+0' : 'None' ,
-274 'poor_near_poor2.0+10' : '10% to poor and near poor (2.0)' ,
-275 'poor_near_poor2.0+30' : '30% to poor and near poor (2.0)' ,
-276 'poor_near_poor2.0+50' : '50% to poor and near poor (2.0)' ,
-277 'poor_near_poor2.0+100' : '100% to poor and near poor (2.0)' }
-278 df = outcomes . copy ()
-279 df [ 'my_policy' ] = df [ 'my_policy' ] . replace ( policy_name_mapper )
-280 df [ 'my_policy' ] = pd . Categorical ( df [ 'my_policy' ], categories = [ 'None' , '10% to all' , '30% to all' , '50% to all' , '100% to all' ,
-281 '10% to poor' , '30% to poor' , '50% to poor' , '100% to poor' ,
-282 '10% to poor and near poor (1.25)' , '30% to poor and near poor (1.25)' , '50% to poor and near poor (1.25)' , '100% to poor and near poor (1.25)' ,
-283 '10% to poor and near poor (2.0)' , '30% to poor and near poor (2.0)' , '50% to poor and near poor (2.0)' , '100% to poor and near poor (2.0)' ], ordered = True )
-284 df . rename ( columns = { 'my_policy' : 'Policy' ,
-285 'district' : 'District' }, inplace = True )
-286 df . rename ( columns = { 'annual_average_consumption_loss_pct' : 'Annual average consumption loss (%)' ,
-287 'n_new_poor' : 'Number of new poor' },
-288 inplace = True )
-289 df [ 'Policy ID' ] = df [ 'Policy' ] . cat . codes
-290 return df
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/src/data/prepare.html b/docs/src/data/prepare.html
deleted file mode 100644
index bb92eb8..0000000
--- a/docs/src/data/prepare.html
+++ /dev/null
@@ -1,1984 +0,0 @@
-
-
-
-
-
-
- src.data.prepare API documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- View Source
-
- 1 from sklearn.linear_model import LinearRegression
- 2 import numpy.polynomial.polynomial as poly
- 3 from sklearn.preprocessing import FunctionTransformer
- 4 import pandas as pd
- 5 import matplotlib.pyplot as plt
- 6 import numpy as np
- 7
- 8
- 9 # ---------------------------------------------------------------------------- #
- 10 # Asset damage data preparation #
- 11 # ---------------------------------------------------------------------------- #
- 12
- 13 def prepare_asset_damage ( country : str , scale : str , return_period : int = 100 ) -> None :
- 14 '''Prepare district-level asset damage data and save it into a XLSX file.'''
- 15 if country == 'Saint Lucia' :
- 16 if scale == 'district' :
- 17 # Load raw data
- 18 df = pd . read_excel (
- 19 '../../data/raw/asset_damage/Saint Lucia/St Lucia 2015 exposure summary.xlsx' , sheet_name = 'total by parish' , skiprows = 1 )
- 20 # Remove redundant columns
- 21 df . drop ( df . columns [ 0 ], axis = 1 , inplace = True )
- 22 # Even though the data is by `parish``, let's call the corresponding column `district``
- 23 df . rename ( columns = { 'Unnamed: 1' : 'district' }, inplace = True )
- 24 # !: Check whether rp is = 100 given the data
- 25 df [ 'rp' ] = 100
- 26 df . rename (
- 27 columns = { 'Combined Total' : 'exposed_value' }, inplace = True )
- 28
- 29 # !: Replace with the real data
- 30 # Let's assume that PML is equal to AAL % by district * by the PML for the whole country
- 31 # These values are from PML Results 19022016 SaintLucia FinalSummary2.xlsx
- 32 total_pml = { 10 : 351733.75 , # 3,517,337.50
- 33 50 : 23523224.51 , # 2,352,322,451.00
- 34 100 : 59802419.04 , # 5,980,241,904.00
- 35 250 : 147799213.30 , # 14,779,921,330.00
- 36 500 : 248310895.20 , # 24,831,089,520.00
- 37 1000 : 377593847.00 } # 37,759,384,700.00
- 38 aal = pd . read_excel (
- 39 '../../data/processed/asset_damage/Saint Lucia/AAL Results 19022016 StLucia FinalSummary2 adjusted.xlsx' , sheet_name = 'AAL St. Lucia Province' )
- 40 aal . set_index ( 'Name' , inplace = True )
- 41 aal = aal [[ 'AAL as % o f Total AAL' ]]
- 42 aal . columns = [ 'pml' ]
- 43 aal = aal [ aal . index . notnull ()]
- 44 pml = aal . multiply ( total_pml [ return_period ])
- 45 df = pd . merge ( df , pml , left_on = 'district' , right_index = True )
- 46 df . to_excel (
- 47 f '../../data/processed/asset_damage/ { country } / { country } .xlsx' , index = False )
- 48 else :
- 49 raise ValueError (
- 50 'Only `district` scale is supported for Saint Lucia.' )
- 51 else :
- 52 raise ValueError ( 'Only `Saint Lucia` is supported.' )
- 53
- 54
- 55 # ---------------------------------------------------------------------------- #
- 56 # Household data preparation #
- 57 # ---------------------------------------------------------------------------- #
- 58
- 59 # Prepare Saint Lucia data as an input into simulation model.
- 60
- 61 # There are 5 inputs into the simulation model:
- 62 # * 14 parameters in `parameters.xlsx` (incl. constants, uncertainties, simulation, scenario and policy parameters);
- 63 # * 3 assest damage parameters from the assest damage file (e.g. `Saint Lucia.xlsx`);
- 64 # * N model's algorithms parameters in `algorithms_parameters.xlsx`;
- 65 # * Average capital productivity (computed based on some values of household survey data);
- 66 # * A household survey (e.g. `saint_lucia.csv`).
- 67
- 68 # Here we going to prepare the latest - the household survey.
- 69 # Each row of the data is a household and each column is an attribute.
- 70 # We need to prepare it to match the format of the simulation model.
- 71 # Here is the list of columns that we need to have:
- 72
- 73 # * `hhid` - household id,
- 74 # * `popwgt` - float: [0,inf] (?: Maybe put a cap on this?),
- 75 # * `hhsize` - household size,
- 76 # * `hhweight` - household weight,
- 77 # * `state` - state, str
- 78 # * `aeexp`- float: [0,inf] (?: Maybe put a cap on this?)
- 79 # * `hhexp` - float: [0,inf] (?: Maybe put a cap on this?)
- 80 # * `is_poor` - boolean: False or True,
- 81 # * `aeinc` - float: [0,inf] (?: Maybe put a cap on this?)
- 82 # * `aesoc` - float: [0,inf] (?: Maybe put a cap on this?)
- 83 # * `k_house_ae` - float: [0,inf (?: Maybe put a cap on this?)]
- 84 # * `v_init` - initial vulnerability, float: [0,1]
- 85 # * `inc_safetynet_frac` - float: [0,1]
- 86 # * `delta_tax_safety` - float
- 87 # * `houses_owned` - int: [0,inf] (?: Maybe put a cap on this?)
- 88 # * `own_rent` - string: "own" or "rent"
- 89 # * `aeexp_house` - float
- 90 # * `percentile` - int: [1,100]
- 91 # * `decile` - int: [1,10]
- 92 # * `quintile` - int: [1,5]
- 93
- 94 # Here is the list of what we have at the very end.
- 95 # V - we have it, X - we don't have it, ! - we must have it, ? - we don't know what it is.
- 96 # hhid V
- 97 # popwgt V
- 98 # hhsize -> hhsize_ae ?
- 99 # hhweight -> hhwgt ?
-100 # state X
-101 # aaexp V
-102 # hhexp X
-103 # ispoor V
-104 # aeinc V
-105 # aesoc V
-106 # k_house_ae V
-107 # v_init V
-108 # inc_safetynet_frac X
-109 # delta_tax_safety X !
-110 # houses_owned X
-111 # own_rent V
-112 # aaexp_house V
-113 # percentile X
-114 # decile V
-115 # quintile V
-116
-117 def prepare_household_survey ( country : str ) -> None :
-118 '''Prepare data for the simulation model.
-119
-120 Parameters
-121 ----------
-122 country : str
-123
-124 Raises
-125 ------
-126 ValueError
-127 If the country is not supported.
-128
-129 '''
-130 # Data preprocessing description:
-131 # 0. Load raw data
-132 # 1. Change `parentid1` to `hhid`
-133 # 2. Add `is_rural` column. 0 if `urban` is URBAN, if `urban` is RURAL then 1.
-134 # 3. Rename `tvalassets` to `kreported`.
-135 # 4. Rename a set of columns.
-136 # 5. Calculate some household attributes. Need to figure out what they mean.
-137 # 6. Add `financial_inst` column which has info on bank or credit union.
-138 # 7. Decode income attributes.
-139 # 8. Calculate some income attributes. Need to figure out what they mean.
-140 # 9. Decode housing attributes.
-141 # 10. Add new housing attributes. Need to figure out what they mean.
-142 # 11. Add new insurance attributes. Need to figure out what they mean.
-143 # 12. Calculate some housing attributes. Need to figure out what they mean.
-144 # 13. Calculate povery attributes. Need to figure out what they mean.
-145 # 14. Assign vulnerability by type of house.
-146 # 15. Subset columns of interest.
-147 # 16. Check which columns do we have and which do we miss.
-148 # 17. Add missing columns.
-149 # 18. Merge districts.
-150 # 19. Save data.
-151
-152 if country != 'Saint Lucia' :
-153 raise ValueError ( 'Currently only Saint Lucia is supported.' )
-154
-155 print_statistics = True
-156 data = load_data ( print_statistics = print_statistics )
-157
-158 # * Note that the sequence of the functions is important
-159 result = ( start_pipeline ( data )
-160 . pipe ( add_is_rural_column , print_statistics = print_statistics )
-161 . pipe ( rename_assets_column )
-162 . pipe ( rename_other_columns )
-163 . pipe ( calculate_household_attributes )
-164 . pipe ( get_bank_or_credit_union )
-165 . pipe ( decode_demographic_attributes )
-166 . pipe ( decode_income_attributes )
-167 . pipe ( calculate_income_attributes )
-168 . pipe ( decode_housing_attributes )
-169 . pipe ( add_housing_attributes )
-170 . pipe ( add_insurance_attributes )
-171 . pipe ( calculate_housing_attributes )
-172 . pipe ( calculate_poverty_attributes )
-173 . pipe ( assign_housing_vulnerability )
-174 . pipe ( subset_columns )
-175 . pipe ( check_columns )
-176 . pipe ( add_missing_columns , missing_columns = [ 'delta_tax_safety' ])
-177 . pipe ( merge_districts )
-178 )
-179
-180 result . to_csv (
-181 f '../../data/processed/household_survey/ { country } / { country } .csv ' )
-182
-183
-184 def load_data ( print_statistics : bool = True ) -> pd . DataFrame :
-185 """Load the raw data."""
-186 # Read the raw data
-187 # * This dataset is the combined version of the household and persons files on parentid1
-188 data = pd . read_csv (
-189 '../../data/raw/household_survey/Saint Lucia/SLCHBS2016PersonV12_Housing.csv' , low_memory = False )
-190 data . rename ( columns = { 'parentid1' : 'hhid' }, inplace = True )
-191
-192 # Set the index to the household id
-193 data . set_index ( 'hhid' , inplace = True )
-194
-195 if print_statistics :
-196 print ( 'Number of rows: ' , data . shape [ 0 ])
-197 print ( 'Number of columns: ' , data . shape [ 1 ])
-198 print ( 'Number of duplicates based on index: ' ,
-199 data . index . duplicated () . sum ())
-200
-201 return data
-202
-203
-204 def start_pipeline ( data : pd . DataFrame ):
-205 """Start the data processing pipeline."""
-206 return data . copy ()
-207
-208
-209 def add_is_rural_column ( data : pd . DataFrame , print_statistics : bool = True ) -> pd . DataFrame :
-210 """Create a new column that indicates whether the household is rural or not."""
-211 data [ 'is_rural' ] = 0
-212 data . loc [ data [ 'urban' ] == 'RURAL' , 'is_rural' ] = 1
-213 if print_statistics :
-214 print ( 'Number of rural households: ' , data [ 'is_rural' ] . sum ())
-215 print ( 'Number of urban households: ' ,
-216 data . shape [ 0 ] - data [ 'is_rural' ] . sum ())
-217 return data
-218
-219
-220 def rename_assets_column ( data : pd . DataFrame ) -> pd . DataFrame :
-221 """Rename the assets column to be more descriptive."""
-222 data . rename ( columns = { 'tvalassets' : 'kreported' }, inplace = True )
-223 return data
-224
-225
-226 def rename_other_columns ( data : pd . DataFrame ) -> pd . DataFrame :
-227 '''Rename a set of columns. See function for details.'''
-228 data = data . rename ( columns = { 'DISTRICT_NAME' : 'district' ,
-229 'persons' : 'hhsize' ,
-230 'totexp.x' : 'hhexp' ,
-231 'pcexpae.x' : 'aeexp' ,
-232 'hincome' : 'hhinc' ,
-233 'WT.x' : 'pwgt' ,
-234 'food.x' : 'hhexp_food' })
-235 return data
-236
-237 # ? What does it mean?
-238 # hhwgt = WT.y from full_df with group by parentid1 or WT from House data
-239 # pwgt = WT.x from full_df or WT from Person data
-240
-241 # hhsize = number of people in a household
-242
-243 # ? What does it mean
-244 # ! Data doesn't have this column
-245 # pcinc = annual consumption per head
-246
-247 # ! That's quite an assumption
-248 # hhinc = pcinc * hhsize
-249
-250 # p4_23 is monthly income
-251 # p4_1 is months worked
-252 # pincome is monthly income
-253 # pincome_oth is annual other income
-254 # aincome is pincome * p4_1 + pincome_oth
-255
-256 # ! Data doesn't have this column
-257 # hincome is the sum of aincome
-258
-259
-260 def calculate_household_attributes ( data : pd . DataFrame ) -> pd . DataFrame :
-261 lower = 1
-262 fill_na = 1
-263 data [ 'popwgt' ] = data . groupby ( 'hhid' )[ 'pwgt' ] . transform ( 'sum' )
-264 data [ 'hhwgt' ] = data [ 'popwgt' ] / data [ 'hhsize' ]
-265 data [ 'hhsize_ae' ] = ( data [ 'hhexp' ] / data [ 'aeexp' ]
-266 ) . fillna ( fill_na ) . clip ( lower = lower )
-267 data [ 'aewgt' ] = data [ 'pwgt' ] * ( data [ 'hhsize_ae' ] / data [ 'hhsize' ])
-268 return data
-269
-270
-271 def get_bank_or_credit_union ( data : pd . DataFrame ) -> pd . DataFrame :
-272 data [ 'financial_inst' ] = 0
-273 data . loc [ data [ 'p1_11__3' ] == 'yes - bank' , 'financial_inst' ] = 1
-274 data . loc [ data [ 'p1_11__2' ] == 'yes - bank' , 'financial_inst' ] = 1
-275 data . loc [ data [ 'p1_11__2' ] == 'yes - credit union' , 'financial_inst' ] = 1
-276 data . loc [ data [ 'p1_11__1' ] == 'yes - bank' , 'financial_inst' ] = 1
-277 data . loc [ data [ 'p1_11__1' ] == 'yes - credit union' , 'financial_inst' ] = 1
-278 return data
-279
-280
-281 def decode_demographic_attributes ( data : pd . DataFrame ) -> pd . DataFrame :
-282 '''Decode the demographic attributes.'''
-283 data = data . rename ( columns = { 'p1_1' : 'role' ,
-284 'p1_2' : 'sex' ,
-285 'p1_3' : 'age' ,
-286 'p1_4' : 'race' ,
-287 'p1_5' : 'religion' ,
-288 'p1_6' : 'marital_status' ,
-289 'p1_7' : 'cellphone' })
-290 return data
-291
-292
-293 def decode_income_attributes ( data : pd . DataFrame ) -> pd . DataFrame :
-294 '''Decode the income-related attributes.'''
-295 data = data . rename ( columns = {
-296 # 'p1_11':'bank_account',
-297 'p4_1' : 'months_worked' ,
-298 'inc2231002' : 'other_entrepreneurial' ,
-299 'inc2331001' : 'remits_intl' ,
-300 'inc2341001' : 'rental_income' ,
-301 'inc2351001' : 'dividends' , # other
-302 'inc2361001' : 'interest' , # other
-303 'inc2361002' : 'other_investment_income' , # other
-304 'inc2371001' : 'pension_public' , # UCT
-305 'inc2371002' : 'pension_private_LCA' , # pension private
-306 'inc2371003' : 'pension_private_int' , # pension private
-307 'inc2371004' : 'social_security' , # UCT
-308 # 'inc2381001':'annuity', # other
-309 'inc2381002' : 'public_assistance' , # CCT
-310 'inc2381003' : 'child_support' , # other
-311 'inc2391001' : 'scholarships' , # other
-312 'inc2391002' : 'financial_aid' , # other
-313 'inc2391003' : 'alimony' , # other
-314 'inc2391099' : 'mystery'
-315 })
-316 return data
-317
-318
-319 def calculate_income_attributes ( data : pd . DataFrame ) -> pd . DataFrame :
-320 data [ 'remits_dom' ] = 0
-321
-322 # Primary job income
-323 data [ 'primary_income' ] = data [[ 'months_worked' , 'pincome' ]] . prod ( axis = 1 )
-324
-325 # Secondary income
-326 data [ 'cct' ] = data [ 'public_assistance' ] . copy ()
-327 data [ 'uct' ] = data [[ 'pension_public' , 'social_security' ]] . sum ( axis = 1 )
-328 data [ 'remits' ] = data [[ 'remits_intl' , 'remits_dom' ]] . sum ( axis = 1 )
-329 data [ 'other_sources' ] = data [[ 'dividends' , 'interest' , 'child_support' , 'alimony' , 'financial_aid' ,
-330 'scholarships' , 'pension_private_LCA' , 'pension_private_int' , 'other_investment_income' , 'mystery' ]] . sum ( axis = 1 )
-331 data [ 'secondary_income' ] = data [[ 'other_entrepreneurial' , 'cct' ,
-332 'uct' , 'remits' , 'rental_income' , 'other_sources' ]] . sum ( axis = 1 )
-333
-334 # Total income
-335 data [ 'total_income' ] = data [[
-336 'primary_income' , 'secondary_income' ]] . sum ( axis = 1 )
-337
-338 return data
-339
-340
-341 def decode_housing_attributes ( data : pd . DataFrame ) -> pd . DataFrame :
-342 '''Decode the housing-related attributes.'''
-343 data = data . rename ( columns = { 's2' : 'own_rent' ,
-344 # owner-occupied
-345 'c1900105' : 'mortgage_monthly' ,
-346 'c1900104' : 'domicile_value' ,
-347 'c1900101' : 'new_home_purchase_price' ,
-348 'c1900103' : 'new_home_mortgage_monthly' ,
-349 'c1800501' : 'rental_income_furnished' ,
-350 'c1800502' : 'rental_income_unfurnished' ,
-351 'c1800503' : 'rental_income_business' ,
-352 'c0421101' : 'imputed_rent_monthly' ,
-353 'c1252101' : 'insurance_premium' ,
-354 # rental
-355 'c0411100' : 'actual_rent_monthly' ,
-356 # condition & construction
-357 's9q1' : 'had_shock' ,
-358 'h1_2' : 'walls' ,
-359 'h1_3' : 'roof' ,
-360 'h1_13' : 'yr_house_built' })
-361 return data
-362
-363
-364 def add_housing_attributes ( data : pd . DataFrame ) -> pd . DataFrame :
-365 '''Introduce new housing attributes.'''
-366 # ! An assumption
-367 data [ 'own_rent' ] = data [ 'own_rent' ] . replace ({ 'own or rent free' : 'own' })
-368 data [ 'home_insured' ] = data [ 'insurance_premium' ] > 0
-369 return data
-370
-371
-372 def add_insurance_attributes ( data : pd . DataFrame ) -> pd . DataFrame :
-373 # ? What does it mean?
-374 # National insurance corporation (unemployment)
-375 data [ 'NIC_enrolled' ] = data [ 'p4_18' ] . isin ([ 'employer' , 'self-employed' ])
-376 data [ 'NIC_recipient' ] = data [ 'p4_17' ] . isin ([ 'yes, from the nic' ])
-377
-378 # Health insurance
-379 data = data . rename ( columns = { 'p2_5' : 'health_insurance' })
-380 return data
-381
-382
-383 def calculate_housing_attributes ( data : pd . DataFrame ) -> pd . DataFrame :
-384 # Predict domicile value for hh that rent
-385 data [ 'k_house' ] = data [ 'domicile_value' ] . copy () . fillna ( 0 )
-386 # total rent per capita per year
-387 data [ 'hhexp_house' ] = 12 * data [ 'imputed_rent_monthly' ] . copy ()
-388 data [ 'hhexp_house' ] . update ( 12 * data [ 'actual_rent_monthly' ])
-389 data [ 'hhexp_house' ] = data [ 'hhexp_house' ] . clip ( lower = 0 ) . fillna ( 0 )
-390
-391 # Urban population
-392 training_slc = ( data [ 'domicile_value' ] > 10 * data [ 'imputed_rent_monthly' ]
-393 ) & ( data [ 'domicile_value' ] < 1E6 ) & ( data [ 'is_rural' ] == 0 )
-394 urban_predictor = linear_regression ( data . loc [ training_slc ] . dropna (
-395 subset = [ 'domicile_value' , 'imputed_rent_monthly' ]), 'imputed_rent_monthly' , 'domicile_value' , return_model = True )
-396
-397 prediction_slc = ( data [ 'own_rent' ] == 'rent' ) & (
-398 data [ 'is_rural' ] == 0 ) & ( data [ 'actual_rent_monthly' ] is not None )
-399 data . loc [ prediction_slc , 'k_house' ] = urban_predictor . predict (
-400 data . loc [ prediction_slc , 'actual_rent_monthly' ] . values . reshape ( - 1 , 1 ))
-401
-402 # Rural population
-403 training_slc = ( data [ 'domicile_value' ] > 10 * data [ 'imputed_rent_monthly' ]
-404 ) & ( data [ 'domicile_value' ] < 1E6 ) & ( data [ 'is_rural' ] == 1 )
-405 rural_predictor = linear_regression ( data . loc [ training_slc ] . dropna (
-406 subset = [ 'domicile_value' , 'imputed_rent_monthly' ]), 'imputed_rent_monthly' , 'domicile_value' , return_model = True )
-407
-408 prediction_slc = ( data [ 'own_rent' ] == 'rent' ) & (
-409 data [ 'is_rural' ] == 1 ) & ( data [ 'actual_rent_monthly' ] is not None )
-410 data . loc [ prediction_slc , 'k_house' ] = rural_predictor . predict (
-411 data . loc [ prediction_slc , 'actual_rent_monthly' ] . values . reshape ( - 1 , 1 ))
-412
-413 # Correct for the households that reported unreasonably low domicile value
-414 prediction_slc = ( data [ 'own_rent' ] == 'own' ) & ( data [ 'is_rural' ] == 0 ) & (
-415 data [ 'k_house' ] <= 10 * data [ 'imputed_rent_monthly' ])
-416 data . loc [ prediction_slc , 'k_house' ] = urban_predictor . predict (
-417 data . loc [ prediction_slc , 'imputed_rent_monthly' ] . values . reshape ( - 1 , 1 ))
-418
-419 prediction_slc = ( data [ 'own_rent' ] == 'own' ) & ( data [ 'is_rural' ] == 1 ) & (
-420 data [ 'k_house' ] <= 10 * data [ 'imputed_rent_monthly' ])
-421 data . loc [ prediction_slc , 'k_house' ] = rural_predictor . predict (
-422 data . loc [ prediction_slc , 'imputed_rent_monthly' ] . values . reshape ( - 1 , 1 ))
-423
-424 data [ 'k_house' ] = data [ 'k_house' ] . clip ( lower = 0 ) . fillna ( 0 )
-425
-426 return data
-427
-428
-429 def calculate_poverty_attributes ( data : pd . DataFrame ) -> pd . DataFrame :
-430 # Data has four poverty levels:
-431 # (1) $1.90/day = 1345 (ipline190 in dataset)
-432 # (2) $4.00/day = 2890,
-433 # (3) indigence line based on food is 2123 (indline in dataset),
-434 # (4) relative poverty line for food and non-food items is 6443 (povline in dataset)
-435 # Saint Lucia's poverty line is 1.90 * 365 = $689.7 US Dollars per year,
-436 # discounting using the PPP exchange rate of 1.952
-437 # the international poverty line for Saint Lucia is 1.90 * 1.952 * 365 = EC $1, 354 (0.7% in doc have 0.66%)
-438 # US $4 a day PPP is 4 * 1.952 * 365 = EC $2,890 (4.4% in doc have 4%)
-439 # poverty highest in Dennery and Vieux-Fort
-440
-441 # Domestic lines
-442 # !: Do not hardcode these values
-443 # !: Check with Bramka
-444 data [ 'pov_line' ] = 6443
-445 data [ 'vul_line' ] = 8053.75
-446 data [ 'is_poor' ] = data [ 'aeexp' ] <= data [ 'pov_line' ]
-447
-448 # Load PMT data
-449 # ? What is PMT?
-450 # TODO: Merge PMT with data
-451 # !: I don't have this dataset
-452 # pmt = pd.read_stata(inputs + 'SLNET_16April.dta')
-453
-454 # Consumption quintiles and deciles
-455 data = data . rename ( columns = { 'quintile.y' : 'quintile' ,
-456 'decile.y' : 'decile' })
-457
-458 # print('income = {} mil. EC$'.format(round(1E-6*dfout[['aewgt','aeinc']].prod(axis=1).sum(),1)))
-459 # print(' = {} EC$/cap'.format(round(dfout[['aewgt','aeinc']].prod(axis=1).sum()/dfout['pwgt'].sum(),1)))
-460
-461 # Individual income
-462 for _i in [ 'primary_income_ae' , 'cct_ae' , 'uct_ae' , 'remits_ae' , 'other_sources_ae' ]:
-463 data [ _i ] = data . groupby ( 'hhid' )[ _i . replace ( '_ae' , '' )] . transform (
-464 'sum' ) . multiply ( 1 / data [ 'hhsize_ae' ])
-465
-466 # Household consumption
-467 data [ 'imputed_rent_monthly' ] = data [ 'imputed_rent_monthly' ] . fillna ( 0 )
-468 data [ 'housing_service_ae' ] = data . groupby (
-469 'hhid' )[ 'imputed_rent_monthly' ] . transform ( 'mean' ) . multiply ( 12. / data [ 'hhsize_ae' ])
-470 data [ 'aeexp_house' ] = data [ 'hhexp_house' ] / data [ 'hhsize_ae' ]
-471 data [ 'aeexp_food' ] = data [ 'hhexp_food' ] / data [ 'hhsize_ae' ]
-472 data [ 'aeexp_other' ] = data [ 'aeexp' ] - \
-473 data [[ 'aeexp_house' , 'aeexp_food' ]] . sum ( axis = 1 )
-474
-475 # sum to households
-476 data [ 'aesoc' ] = data [ 'cct_ae' ] . copy ()
-477 data [ 'aeinc' ] = data [[ 'primary_income_ae' , 'cct_ae' , 'uct_ae' ,
-478 'remits_ae' , 'other_sources_ae' , 'housing_service_ae' ]] . sum ( axis = 1 )
-479
-480 data [ 'k_house_ae' ] = data [ 'k_house' ] / data [ 'hhsize_ae' ]
-481 return data
-482
-483
-484 def assign_housing_vulnerability ( data : pd . DataFrame ) -> pd . DataFrame :
-485 # !: This is quite random!
-486 # TODO: Do not hard code parameters here. Move them to a config file.
-487 data [ 'walls' ] . fillna ( 'others' , inplace = True )
-488 data [ 'v_walls' ] = 0.1
-489 data . loc [ data [ 'walls' ] . isin (
-490 [ 'brick/blocks' , 'concrete/concrete blocks' ]), 'v_walls' ] = 0.35
-491 data . loc [ data [ 'walls' ] . isin ([ 'wood & concrete' ]), 'v_walls' ] = 0.5
-492 data . loc [ data [ 'walls' ] . isin ([ 'wood/timber' ]), 'v_walls' ] = 0.6
-493 data . loc [ data [ 'walls' ] . isin ([ 'plywood' ]), 'v_walls' ] = 0.7
-494 data . loc [ data [ 'walls' ] . isin (
-495 [ 'makeshift' , 'others' , 'other/dont know' ]), 'v_walls' ] = 0.8
-496 data [ 'roof' ] . fillna ( 'others' , inplace = True )
-497 data [ 'v_roof' ] = 0.75
-498 data . loc [ data [ 'roof' ] . isin (
-499 [ 'sheet metal (galvanize, galvalume)' ]), 'v_roof' ] = 0.5
-500 data [ 'v_init' ] = 0.5 * data [ 'v_roof' ] + 0.5 * data [ 'v_walls' ]
-501 return data
-502
-503
-504 def subset_columns ( data : pd . DataFrame ) -> pd . DataFrame :
-505 '''Subset columns of interest.'''
-506 columns_of_interest = [ 'district' ,
-507 'is_rural' ,
-508 'hhwgt' ,
-509 'hhsize_ae' ,
-510 'popwgt' ,
-511 'aeinc' ,
-512 'aesoc' ,
-513 'k_house_ae' ,
-514 'own_rent' ,
-515 'aeexp' ,
-516 'aeexp_house' ,
-517 'aeexp_food' ,
-518 'aeexp_other' ,
-519 'is_poor' ,
-520 'v_init' ,
-521 'v_walls' ,
-522 'v_roof' ,
-523 'walls' ,
-524 'roof' ,
-525 'quintile' ,
-526 'decile' ,
-527 'primary_income_ae' ,
-528 'cct_ae' ,
-529 'uct_ae' , 'remits_ae' ,
-530 'other_sources_ae' ,
-531 'housing_service_ae' ,
-532 'pov_line' ,
-533 'vul_line' ]
-534 result = data . loc [ ~ data . index . duplicated (
-535 keep = 'first' ), columns_of_interest ]
-536 result [ 'aewgt' ] = data [ 'aewgt' ] . groupby ( level = 'hhid' ) . sum ()
-537
-538 # Keep characteristics of head of household
-539 household_head_columns = [ 'sex' ,
-540 'age' ,
-541 'race' ,
-542 'religion' ,
-543 'marital_status' ,
-544 'cellphone' ,
-545 'health_insurance' ,
-546 'home_insured' ] # ,'bank_account']
-547 result [ household_head_columns ] = data . loc [ data [ 'role' ]
-548 == 'head' , household_head_columns ]
-549 return result
-550
-551
-552 def check_columns ( data : pd . DataFrame ) -> pd . DataFrame :
-553
-554 # These are the columns of the India case
-555 used_columns = [
-556 # 'hhid',
-557 'aeexp' ,
-558 'is_poor' ,
-559 'aeinc' ,
-560 'aesoc' ,
-561 'k_house_ae' ,
-562 'v_init' ,
-563 # 'delta_tax_safety',
-564 'own_rent' ,
-565 'aeexp_house' ,
-566 ]
-567
-568 extra_columns = [
-569 'popwgt' , # used, but seems to be not essential, just for writing
-570 ]
-571
-572 not_used_columns = [
-573 'hhsize' ,
-574 'hhweight' ,
-575 'state' ,
-576 'hhexp' ,
-577 'inc_safetynet_frac' ,
-578 'houses_owned' ,
-579 'percentile' ,
-580 'decile' ,
-581 'quintile'
-582 ]
-583
-584 # Check whether the new data has all columns that we need
-585 missing_columns = []
-586
-587 for column in used_columns :
-588 if column not in data . columns :
-589 missing_columns . append ( column )
-590
-591 # Check what columns we have besides the ones we need from used_columns
-592 extra_columns = [
-593 column for column in data . columns if column not in used_columns ]
-594 print ( f 'We have the following extra columns: { extra_columns } ' )
-595
-596 if len ( missing_columns ) > 0 :
-597 raise ValueError ( f 'Missing columns: { missing_columns } ' )
-598
-599 return data
-600
-601
-602 def add_missing_columns ( data : pd . DataFrame , missing_columns : list ) -> pd . DataFrame :
-603 '''Manually add missing columns to the data.'''
-604 for column in missing_columns :
-605 data [ column ] = 0
-606 return data
-607
-608
-609 def merge_districts ( data : pd . DataFrame ) -> pd . DataFrame :
-610 # !: We merged two districts into one
-611 data [ 'district_original' ] = data [ 'district' ]
-612 data . replace ({ 'district' : { 'Castries Sub-Urban' : 'Castries' ,
-613 'Castries City' : 'Castries' }}, inplace = True )
-614 return data
-615
-616
-617 # Some regression-alike functions
-618 # * I did not test them
-619 np . random . seed ( 123 )
-620
-621
-622 def exponential_regression ( data : pd . DataFrame , X_column : str , y_column : str , weights : np . array = None , return_model : bool = False ) -> tuple [ np . array , float ]:
-623 X = data [ X_column ] . values . reshape ( - 1 , 1 )
-624 y = data [ y_column ] . values . reshape ( - 1 , 1 )
-625 transformer = FunctionTransformer ( np . log , validate = True )
-626 y_transformed = transformer . fit_transform ( y )
-627
-628 lr = LinearRegression ()
-629 lr . fit ( X , y_transformed , sample_weight = weights )
-630 y_pred = lr . predict ( X )
-631 coef = lr . coef_
-632 r2 = lr . score ( X , y_transformed , sample_weight = weights )
-633 if return_model :
-634 return lr
-635 else :
-636 return y_pred , coef , r2
-637
-638
-639 def polynomial_regression ( data : pd . DataFrame ,
-640 X_column : str ,
-641 y_column : str ,
-642 power : int ,
-643 weights : np . array = None ,
-644 X_new : np . array = None ,
-645 X_start : int = 0 ,
-646 X_end : int = 40 ,
-647 X_num : int = 100 ):
-648 # !: Weights are not used in this function
-649 X = data [ X_column ] . squeeze () . T
-650 y = data [ y_column ] . squeeze () . T
-651 coef = poly . polyfit ( X , y , power )
-652
-653 if X_new is None :
-654 X_new = np . linspace ( X_start , X_end , num = X_num )
-655
-656 f = poly . polyval ( X_new , coef )
-657
-658 return X_new , f
-659
-660
-661 def linear_regression ( data : pd . DataFrame , X_column : str , y_column : str , weights : np . array = None , return_model : bool = False ) -> tuple [ np . array , float , float ]:
-662 '''Do a linear regression on the data and return the predicted values, the coefficient and the r2 score.'''
-663 X = data [ X_column ] . values . reshape ( - 1 , 1 )
-664 y = data [ y_column ] . values . reshape ( - 1 , 1 )
-665 lr = LinearRegression ()
-666 lr . fit ( X , y , sample_weight = weights )
-667 y_pred = lr . predict ( X )
-668 coef = lr . coef_
-669 r2 = lr . score ( X , y , sample_weight = weights )
-670 if return_model :
-671 return lr
-672 else :
-673 return y_pred , coef , r2
-674
-675 # ---------------------------------------------------------------------------- #
-676 # Run data preparation pipelines #
-677 # ---------------------------------------------------------------------------- #
-678
-679
-680 # prepare_household_survey(country='Saint Lucia')
-681 # prepare_asset_damage(country='Saint Lucia',
-682 # scale='district', return_period=100)
-
-
-
-
-
-
-
-
- def
- prepare_asset_damage (country : str , scale : str , return_period : int = 100 ) -> None :
-
- View Source
-
-
-
- 14 def prepare_asset_damage ( country : str , scale : str , return_period : int = 100 ) -> None :
-15 '''Prepare district-level asset damage data and save it into a XLSX file.'''
-16 if country == 'Saint Lucia' :
-17 if scale == 'district' :
-18 # Load raw data
-19 df = pd . read_excel (
-20 '../../data/raw/asset_damage/Saint Lucia/St Lucia 2015 exposure summary.xlsx' , sheet_name = 'total by parish' , skiprows = 1 )
-21 # Remove redundant columns
-22 df . drop ( df . columns [ 0 ], axis = 1 , inplace = True )
-23 # Even though the data is by `parish``, let's call the corresponding column `district``
-24 df . rename ( columns = { 'Unnamed: 1' : 'district' }, inplace = True )
-25 # !: Check whether rp is = 100 given the data
-26 df [ 'rp' ] = 100
-27 df . rename (
-28 columns = { 'Combined Total' : 'exposed_value' }, inplace = True )
-29
-30 # !: Replace with the real data
-31 # Let's assume that PML is equal to AAL % by district * by the PML for the whole country
-32 # These values are from PML Results 19022016 SaintLucia FinalSummary2.xlsx
-33 total_pml = { 10 : 351733.75 , # 3,517,337.50
-34 50 : 23523224.51 , # 2,352,322,451.00
-35 100 : 59802419.04 , # 5,980,241,904.00
-36 250 : 147799213.30 , # 14,779,921,330.00
-37 500 : 248310895.20 , # 24,831,089,520.00
-38 1000 : 377593847.00 } # 37,759,384,700.00
-39 aal = pd . read_excel (
-40 '../../data/processed/asset_damage/Saint Lucia/AAL Results 19022016 StLucia FinalSummary2 adjusted.xlsx' , sheet_name = 'AAL St. Lucia Province' )
-41 aal . set_index ( 'Name' , inplace = True )
-42 aal = aal [[ 'AAL as % o f Total AAL' ]]
-43 aal . columns = [ 'pml' ]
-44 aal = aal [ aal . index . notnull ()]
-45 pml = aal . multiply ( total_pml [ return_period ])
-46 df = pd . merge ( df , pml , left_on = 'district' , right_index = True )
-47 df . to_excel (
-48 f '../../data/processed/asset_damage/ { country } / { country } .xlsx' , index = False )
-49 else :
-50 raise ValueError (
-51 'Only `district` scale is supported for Saint Lucia.' )
-52 else :
-53 raise ValueError ( 'Only `Saint Lucia` is supported.' )
-
-
-
- Prepare district-level asset damage data and save it into a XLSX file.
-
-
-
-
-
-
-
-
- def
- prepare_household_survey (country : str ) -> None :
-
- View Source
-
-
-
- 118 def prepare_household_survey ( country : str ) -> None :
-119 '''Prepare data for the simulation model.
-120
-121 Parameters
-122 ----------
-123 country : str
-124
-125 Raises
-126 ------
-127 ValueError
-128 If the country is not supported.
-129
-130 '''
-131 # Data preprocessing description:
-132 # 0. Load raw data
-133 # 1. Change `parentid1` to `hhid`
-134 # 2. Add `is_rural` column. 0 if `urban` is URBAN, if `urban` is RURAL then 1.
-135 # 3. Rename `tvalassets` to `kreported`.
-136 # 4. Rename a set of columns.
-137 # 5. Calculate some household attributes. Need to figure out what they mean.
-138 # 6. Add `financial_inst` column which has info on bank or credit union.
-139 # 7. Decode income attributes.
-140 # 8. Calculate some income attributes. Need to figure out what they mean.
-141 # 9. Decode housing attributes.
-142 # 10. Add new housing attributes. Need to figure out what they mean.
-143 # 11. Add new insurance attributes. Need to figure out what they mean.
-144 # 12. Calculate some housing attributes. Need to figure out what they mean.
-145 # 13. Calculate povery attributes. Need to figure out what they mean.
-146 # 14. Assign vulnerability by type of house.
-147 # 15. Subset columns of interest.
-148 # 16. Check which columns do we have and which do we miss.
-149 # 17. Add missing columns.
-150 # 18. Merge districts.
-151 # 19. Save data.
-152
-153 if country != 'Saint Lucia' :
-154 raise ValueError ( 'Currently only Saint Lucia is supported.' )
-155
-156 print_statistics = True
-157 data = load_data ( print_statistics = print_statistics )
-158
-159 # * Note that the sequence of the functions is important
-160 result = ( start_pipeline ( data )
-161 . pipe ( add_is_rural_column , print_statistics = print_statistics )
-162 . pipe ( rename_assets_column )
-163 . pipe ( rename_other_columns )
-164 . pipe ( calculate_household_attributes )
-165 . pipe ( get_bank_or_credit_union )
-166 . pipe ( decode_demographic_attributes )
-167 . pipe ( decode_income_attributes )
-168 . pipe ( calculate_income_attributes )
-169 . pipe ( decode_housing_attributes )
-170 . pipe ( add_housing_attributes )
-171 . pipe ( add_insurance_attributes )
-172 . pipe ( calculate_housing_attributes )
-173 . pipe ( calculate_poverty_attributes )
-174 . pipe ( assign_housing_vulnerability )
-175 . pipe ( subset_columns )
-176 . pipe ( check_columns )
-177 . pipe ( add_missing_columns , missing_columns = [ 'delta_tax_safety' ])
-178 . pipe ( merge_districts )
-179 )
-180
-181 result . to_csv (
-182 f '../../data/processed/household_survey/ { country } / { country } .csv ' )
-
-
-
- Prepare data for the simulation model.
-
-
Parameters
-
-
country : str
-
-
Raises
-
-
ValueError
- If the country is not supported.
-
-
-
-
-
-
-
-
-
- def
- start_pipeline (data : pandas . core . frame . DataFrame ):
-
- View Source
-
-
-
- 205 def start_pipeline ( data : pd . DataFrame ):
-206 """Start the data processing pipeline."""
-207 return data . copy ()
-
-
-
- Start the data processing pipeline.
-
-
-
-
-
-
-
-
- def
- add_is_rural_column ( data : pandas . core . frame . DataFrame , print_statistics : bool = True ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 210 def add_is_rural_column ( data : pd . DataFrame , print_statistics : bool = True ) -> pd . DataFrame :
-211 """Create a new column that indicates whether the household is rural or not."""
-212 data [ 'is_rural' ] = 0
-213 data . loc [ data [ 'urban' ] == 'RURAL' , 'is_rural' ] = 1
-214 if print_statistics :
-215 print ( 'Number of rural households: ' , data [ 'is_rural' ] . sum ())
-216 print ( 'Number of urban households: ' ,
-217 data . shape [ 0 ] - data [ 'is_rural' ] . sum ())
-218 return data
-
-
-
- Create a new column that indicates whether the household is rural or not.
-
-
-
-
-
-
-
-
- def
- rename_assets_column (data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 221 def rename_assets_column ( data : pd . DataFrame ) -> pd . DataFrame :
-222 """Rename the assets column to be more descriptive."""
-223 data . rename ( columns = { 'tvalassets' : 'kreported' }, inplace = True )
-224 return data
-
-
-
- Rename the assets column to be more descriptive.
-
-
-
-
-
-
-
-
- def
- rename_other_columns (data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 227 def rename_other_columns ( data : pd . DataFrame ) -> pd . DataFrame :
-228 '''Rename a set of columns. See function for details.'''
-229 data = data . rename ( columns = { 'DISTRICT_NAME' : 'district' ,
-230 'persons' : 'hhsize' ,
-231 'totexp.x' : 'hhexp' ,
-232 'pcexpae.x' : 'aeexp' ,
-233 'hincome' : 'hhinc' ,
-234 'WT.x' : 'pwgt' ,
-235 'food.x' : 'hhexp_food' })
-236 return data
-
-
-
- Rename a set of columns. See function for details.
-
-
-
-
-
-
-
-
-
-
- def
- decode_demographic_attributes (data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 282 def decode_demographic_attributes ( data : pd . DataFrame ) -> pd . DataFrame :
-283 '''Decode the demographic attributes.'''
-284 data = data . rename ( columns = { 'p1_1' : 'role' ,
-285 'p1_2' : 'sex' ,
-286 'p1_3' : 'age' ,
-287 'p1_4' : 'race' ,
-288 'p1_5' : 'religion' ,
-289 'p1_6' : 'marital_status' ,
-290 'p1_7' : 'cellphone' })
-291 return data
-
-
-
- Decode the demographic attributes.
-
-
-
-
-
-
-
-
- def
- decode_income_attributes (data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 294 def decode_income_attributes ( data : pd . DataFrame ) -> pd . DataFrame :
-295 '''Decode the income-related attributes.'''
-296 data = data . rename ( columns = {
-297 # 'p1_11':'bank_account',
-298 'p4_1' : 'months_worked' ,
-299 'inc2231002' : 'other_entrepreneurial' ,
-300 'inc2331001' : 'remits_intl' ,
-301 'inc2341001' : 'rental_income' ,
-302 'inc2351001' : 'dividends' , # other
-303 'inc2361001' : 'interest' , # other
-304 'inc2361002' : 'other_investment_income' , # other
-305 'inc2371001' : 'pension_public' , # UCT
-306 'inc2371002' : 'pension_private_LCA' , # pension private
-307 'inc2371003' : 'pension_private_int' , # pension private
-308 'inc2371004' : 'social_security' , # UCT
-309 # 'inc2381001':'annuity', # other
-310 'inc2381002' : 'public_assistance' , # CCT
-311 'inc2381003' : 'child_support' , # other
-312 'inc2391001' : 'scholarships' , # other
-313 'inc2391002' : 'financial_aid' , # other
-314 'inc2391003' : 'alimony' , # other
-315 'inc2391099' : 'mystery'
-316 })
-317 return data
-
-
-
- Decode the income-related attributes.
-
-
-
-
-
-
-
-
- def
- calculate_income_attributes (data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 320 def calculate_income_attributes ( data : pd . DataFrame ) -> pd . DataFrame :
-321 data [ 'remits_dom' ] = 0
-322
-323 # Primary job income
-324 data [ 'primary_income' ] = data [[ 'months_worked' , 'pincome' ]] . prod ( axis = 1 )
-325
-326 # Secondary income
-327 data [ 'cct' ] = data [ 'public_assistance' ] . copy ()
-328 data [ 'uct' ] = data [[ 'pension_public' , 'social_security' ]] . sum ( axis = 1 )
-329 data [ 'remits' ] = data [[ 'remits_intl' , 'remits_dom' ]] . sum ( axis = 1 )
-330 data [ 'other_sources' ] = data [[ 'dividends' , 'interest' , 'child_support' , 'alimony' , 'financial_aid' ,
-331 'scholarships' , 'pension_private_LCA' , 'pension_private_int' , 'other_investment_income' , 'mystery' ]] . sum ( axis = 1 )
-332 data [ 'secondary_income' ] = data [[ 'other_entrepreneurial' , 'cct' ,
-333 'uct' , 'remits' , 'rental_income' , 'other_sources' ]] . sum ( axis = 1 )
-334
-335 # Total income
-336 data [ 'total_income' ] = data [[
-337 'primary_income' , 'secondary_income' ]] . sum ( axis = 1 )
-338
-339 return data
-
-
-
-
-
-
-
-
-
-
- def
- decode_housing_attributes (data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 342 def decode_housing_attributes ( data : pd . DataFrame ) -> pd . DataFrame :
-343 '''Decode the housing-related attributes.'''
-344 data = data . rename ( columns = { 's2' : 'own_rent' ,
-345 # owner-occupied
-346 'c1900105' : 'mortgage_monthly' ,
-347 'c1900104' : 'domicile_value' ,
-348 'c1900101' : 'new_home_purchase_price' ,
-349 'c1900103' : 'new_home_mortgage_monthly' ,
-350 'c1800501' : 'rental_income_furnished' ,
-351 'c1800502' : 'rental_income_unfurnished' ,
-352 'c1800503' : 'rental_income_business' ,
-353 'c0421101' : 'imputed_rent_monthly' ,
-354 'c1252101' : 'insurance_premium' ,
-355 # rental
-356 'c0411100' : 'actual_rent_monthly' ,
-357 # condition & construction
-358 's9q1' : 'had_shock' ,
-359 'h1_2' : 'walls' ,
-360 'h1_3' : 'roof' ,
-361 'h1_13' : 'yr_house_built' })
-362 return data
-
-
-
- Decode the housing-related attributes.
-
-
-
-
-
-
-
-
- def
- add_housing_attributes (data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 365 def add_housing_attributes ( data : pd . DataFrame ) -> pd . DataFrame :
-366 '''Introduce new housing attributes.'''
-367 # ! An assumption
-368 data [ 'own_rent' ] = data [ 'own_rent' ] . replace ({ 'own or rent free' : 'own' })
-369 data [ 'home_insured' ] = data [ 'insurance_premium' ] > 0
-370 return data
-
-
-
- Introduce new housing attributes.
-
-
-
-
-
-
-
-
-
- def
- calculate_housing_attributes (data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 384 def calculate_housing_attributes ( data : pd . DataFrame ) -> pd . DataFrame :
-385 # Predict domicile value for hh that rent
-386 data [ 'k_house' ] = data [ 'domicile_value' ] . copy () . fillna ( 0 )
-387 # total rent per capita per year
-388 data [ 'hhexp_house' ] = 12 * data [ 'imputed_rent_monthly' ] . copy ()
-389 data [ 'hhexp_house' ] . update ( 12 * data [ 'actual_rent_monthly' ])
-390 data [ 'hhexp_house' ] = data [ 'hhexp_house' ] . clip ( lower = 0 ) . fillna ( 0 )
-391
-392 # Urban population
-393 training_slc = ( data [ 'domicile_value' ] > 10 * data [ 'imputed_rent_monthly' ]
-394 ) & ( data [ 'domicile_value' ] < 1E6 ) & ( data [ 'is_rural' ] == 0 )
-395 urban_predictor = linear_regression ( data . loc [ training_slc ] . dropna (
-396 subset = [ 'domicile_value' , 'imputed_rent_monthly' ]), 'imputed_rent_monthly' , 'domicile_value' , return_model = True )
-397
-398 prediction_slc = ( data [ 'own_rent' ] == 'rent' ) & (
-399 data [ 'is_rural' ] == 0 ) & ( data [ 'actual_rent_monthly' ] is not None )
-400 data . loc [ prediction_slc , 'k_house' ] = urban_predictor . predict (
-401 data . loc [ prediction_slc , 'actual_rent_monthly' ] . values . reshape ( - 1 , 1 ))
-402
-403 # Rural population
-404 training_slc = ( data [ 'domicile_value' ] > 10 * data [ 'imputed_rent_monthly' ]
-405 ) & ( data [ 'domicile_value' ] < 1E6 ) & ( data [ 'is_rural' ] == 1 )
-406 rural_predictor = linear_regression ( data . loc [ training_slc ] . dropna (
-407 subset = [ 'domicile_value' , 'imputed_rent_monthly' ]), 'imputed_rent_monthly' , 'domicile_value' , return_model = True )
-408
-409 prediction_slc = ( data [ 'own_rent' ] == 'rent' ) & (
-410 data [ 'is_rural' ] == 1 ) & ( data [ 'actual_rent_monthly' ] is not None )
-411 data . loc [ prediction_slc , 'k_house' ] = rural_predictor . predict (
-412 data . loc [ prediction_slc , 'actual_rent_monthly' ] . values . reshape ( - 1 , 1 ))
-413
-414 # Correct for the households that reported unreasonably low domicile value
-415 prediction_slc = ( data [ 'own_rent' ] == 'own' ) & ( data [ 'is_rural' ] == 0 ) & (
-416 data [ 'k_house' ] <= 10 * data [ 'imputed_rent_monthly' ])
-417 data . loc [ prediction_slc , 'k_house' ] = urban_predictor . predict (
-418 data . loc [ prediction_slc , 'imputed_rent_monthly' ] . values . reshape ( - 1 , 1 ))
-419
-420 prediction_slc = ( data [ 'own_rent' ] == 'own' ) & ( data [ 'is_rural' ] == 1 ) & (
-421 data [ 'k_house' ] <= 10 * data [ 'imputed_rent_monthly' ])
-422 data . loc [ prediction_slc , 'k_house' ] = rural_predictor . predict (
-423 data . loc [ prediction_slc , 'imputed_rent_monthly' ] . values . reshape ( - 1 , 1 ))
-424
-425 data [ 'k_house' ] = data [ 'k_house' ] . clip ( lower = 0 ) . fillna ( 0 )
-426
-427 return data
-
-
-
-
-
-
-
-
-
-
- def
- calculate_poverty_attributes (data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 430 def calculate_poverty_attributes ( data : pd . DataFrame ) -> pd . DataFrame :
-431 # Data has four poverty levels:
-432 # (1) $1.90/day = 1345 (ipline190 in dataset)
-433 # (2) $4.00/day = 2890,
-434 # (3) indigence line based on food is 2123 (indline in dataset),
-435 # (4) relative poverty line for food and non-food items is 6443 (povline in dataset)
-436 # Saint Lucia's poverty line is 1.90 * 365 = $689.7 US Dollars per year,
-437 # discounting using the PPP exchange rate of 1.952
-438 # the international poverty line for Saint Lucia is 1.90 * 1.952 * 365 = EC $1, 354 (0.7% in doc have 0.66%)
-439 # US $4 a day PPP is 4 * 1.952 * 365 = EC $2,890 (4.4% in doc have 4%)
-440 # poverty highest in Dennery and Vieux-Fort
-441
-442 # Domestic lines
-443 # !: Do not hardcode these values
-444 # !: Check with Bramka
-445 data [ 'pov_line' ] = 6443
-446 data [ 'vul_line' ] = 8053.75
-447 data [ 'is_poor' ] = data [ 'aeexp' ] <= data [ 'pov_line' ]
-448
-449 # Load PMT data
-450 # ? What is PMT?
-451 # TODO: Merge PMT with data
-452 # !: I don't have this dataset
-453 # pmt = pd.read_stata(inputs + 'SLNET_16April.dta')
-454
-455 # Consumption quintiles and deciles
-456 data = data . rename ( columns = { 'quintile.y' : 'quintile' ,
-457 'decile.y' : 'decile' })
-458
-459 # print('income = {} mil. EC$'.format(round(1E-6*dfout[['aewgt','aeinc']].prod(axis=1).sum(),1)))
-460 # print(' = {} EC$/cap'.format(round(dfout[['aewgt','aeinc']].prod(axis=1).sum()/dfout['pwgt'].sum(),1)))
-461
-462 # Individual income
-463 for _i in [ 'primary_income_ae' , 'cct_ae' , 'uct_ae' , 'remits_ae' , 'other_sources_ae' ]:
-464 data [ _i ] = data . groupby ( 'hhid' )[ _i . replace ( '_ae' , '' )] . transform (
-465 'sum' ) . multiply ( 1 / data [ 'hhsize_ae' ])
-466
-467 # Household consumption
-468 data [ 'imputed_rent_monthly' ] = data [ 'imputed_rent_monthly' ] . fillna ( 0 )
-469 data [ 'housing_service_ae' ] = data . groupby (
-470 'hhid' )[ 'imputed_rent_monthly' ] . transform ( 'mean' ) . multiply ( 12. / data [ 'hhsize_ae' ])
-471 data [ 'aeexp_house' ] = data [ 'hhexp_house' ] / data [ 'hhsize_ae' ]
-472 data [ 'aeexp_food' ] = data [ 'hhexp_food' ] / data [ 'hhsize_ae' ]
-473 data [ 'aeexp_other' ] = data [ 'aeexp' ] - \
-474 data [[ 'aeexp_house' , 'aeexp_food' ]] . sum ( axis = 1 )
-475
-476 # sum to households
-477 data [ 'aesoc' ] = data [ 'cct_ae' ] . copy ()
-478 data [ 'aeinc' ] = data [[ 'primary_income_ae' , 'cct_ae' , 'uct_ae' ,
-479 'remits_ae' , 'other_sources_ae' , 'housing_service_ae' ]] . sum ( axis = 1 )
-480
-481 data [ 'k_house_ae' ] = data [ 'k_house' ] / data [ 'hhsize_ae' ]
-482 return data
-
-
-
-
-
-
-
-
-
-
- def
- assign_housing_vulnerability (data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 485 def assign_housing_vulnerability ( data : pd . DataFrame ) -> pd . DataFrame :
-486 # !: This is quite random!
-487 # TODO: Do not hard code parameters here. Move them to a config file.
-488 data [ 'walls' ] . fillna ( 'others' , inplace = True )
-489 data [ 'v_walls' ] = 0.1
-490 data . loc [ data [ 'walls' ] . isin (
-491 [ 'brick/blocks' , 'concrete/concrete blocks' ]), 'v_walls' ] = 0.35
-492 data . loc [ data [ 'walls' ] . isin ([ 'wood & concrete' ]), 'v_walls' ] = 0.5
-493 data . loc [ data [ 'walls' ] . isin ([ 'wood/timber' ]), 'v_walls' ] = 0.6
-494 data . loc [ data [ 'walls' ] . isin ([ 'plywood' ]), 'v_walls' ] = 0.7
-495 data . loc [ data [ 'walls' ] . isin (
-496 [ 'makeshift' , 'others' , 'other/dont know' ]), 'v_walls' ] = 0.8
-497 data [ 'roof' ] . fillna ( 'others' , inplace = True )
-498 data [ 'v_roof' ] = 0.75
-499 data . loc [ data [ 'roof' ] . isin (
-500 [ 'sheet metal (galvanize, galvalume)' ]), 'v_roof' ] = 0.5
-501 data [ 'v_init' ] = 0.5 * data [ 'v_roof' ] + 0.5 * data [ 'v_walls' ]
-502 return data
-
-
-
-
-
-
-
-
-
-
- def
- subset_columns (data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 505 def subset_columns ( data : pd . DataFrame ) -> pd . DataFrame :
-506 '''Subset columns of interest.'''
-507 columns_of_interest = [ 'district' ,
-508 'is_rural' ,
-509 'hhwgt' ,
-510 'hhsize_ae' ,
-511 'popwgt' ,
-512 'aeinc' ,
-513 'aesoc' ,
-514 'k_house_ae' ,
-515 'own_rent' ,
-516 'aeexp' ,
-517 'aeexp_house' ,
-518 'aeexp_food' ,
-519 'aeexp_other' ,
-520 'is_poor' ,
-521 'v_init' ,
-522 'v_walls' ,
-523 'v_roof' ,
-524 'walls' ,
-525 'roof' ,
-526 'quintile' ,
-527 'decile' ,
-528 'primary_income_ae' ,
-529 'cct_ae' ,
-530 'uct_ae' , 'remits_ae' ,
-531 'other_sources_ae' ,
-532 'housing_service_ae' ,
-533 'pov_line' ,
-534 'vul_line' ]
-535 result = data . loc [ ~ data . index . duplicated (
-536 keep = 'first' ), columns_of_interest ]
-537 result [ 'aewgt' ] = data [ 'aewgt' ] . groupby ( level = 'hhid' ) . sum ()
-538
-539 # Keep characteristics of head of household
-540 household_head_columns = [ 'sex' ,
-541 'age' ,
-542 'race' ,
-543 'religion' ,
-544 'marital_status' ,
-545 'cellphone' ,
-546 'health_insurance' ,
-547 'home_insured' ] # ,'bank_account']
-548 result [ household_head_columns ] = data . loc [ data [ 'role' ]
-549 == 'head' , household_head_columns ]
-550 return result
-
-
-
- Subset columns of interest.
-
-
-
-
-
-
-
-
- def
- check_columns (data : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 553 def check_columns ( data : pd . DataFrame ) -> pd . DataFrame :
-554
-555 # These are the columns of the India case
-556 used_columns = [
-557 # 'hhid',
-558 'aeexp' ,
-559 'is_poor' ,
-560 'aeinc' ,
-561 'aesoc' ,
-562 'k_house_ae' ,
-563 'v_init' ,
-564 # 'delta_tax_safety',
-565 'own_rent' ,
-566 'aeexp_house' ,
-567 ]
-568
-569 extra_columns = [
-570 'popwgt' , # used, but seems to be not essential, just for writing
-571 ]
-572
-573 not_used_columns = [
-574 'hhsize' ,
-575 'hhweight' ,
-576 'state' ,
-577 'hhexp' ,
-578 'inc_safetynet_frac' ,
-579 'houses_owned' ,
-580 'percentile' ,
-581 'decile' ,
-582 'quintile'
-583 ]
-584
-585 # Check whether the new data has all columns that we need
-586 missing_columns = []
-587
-588 for column in used_columns :
-589 if column not in data . columns :
-590 missing_columns . append ( column )
-591
-592 # Check what columns we have besides the ones we need from used_columns
-593 extra_columns = [
-594 column for column in data . columns if column not in used_columns ]
-595 print ( f 'We have the following extra columns: { extra_columns } ' )
-596
-597 if len ( missing_columns ) > 0 :
-598 raise ValueError ( f 'Missing columns: { missing_columns } ' )
-599
-600 return data
-
-
-
-
-
-
-
-
-
-
- def
- add_missing_columns ( data : pandas . core . frame . DataFrame , missing_columns : list ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 603 def add_missing_columns ( data : pd . DataFrame , missing_columns : list ) -> pd . DataFrame :
-604 '''Manually add missing columns to the data.'''
-605 for column in missing_columns :
-606 data [ column ] = 0
-607 return data
-
-
-
- Manually add missing columns to the data.
-
-
-
-
-
-
-
-
-
- def
- exponential_regression ( data : pandas . core . frame . DataFrame , X_column : str , y_column : str , weights : < built - in function array > = None , return_model : bool = False ) -> tuple [ numpy . array , float ] :
-
- View Source
-
-
-
- 623 def exponential_regression ( data : pd . DataFrame , X_column : str , y_column : str , weights : np . array = None , return_model : bool = False ) -> tuple [ np . array , float ]:
-624 X = data [ X_column ] . values . reshape ( - 1 , 1 )
-625 y = data [ y_column ] . values . reshape ( - 1 , 1 )
-626 transformer = FunctionTransformer ( np . log , validate = True )
-627 y_transformed = transformer . fit_transform ( y )
-628
-629 lr = LinearRegression ()
-630 lr . fit ( X , y_transformed , sample_weight = weights )
-631 y_pred = lr . predict ( X )
-632 coef = lr . coef_
-633 r2 = lr . score ( X , y_transformed , sample_weight = weights )
-634 if return_model :
-635 return lr
-636 else :
-637 return y_pred , coef , r2
-
-
-
-
-
-
-
-
-
-
- def
- polynomial_regression ( data : pandas . core . frame . DataFrame , X_column : str , y_column : str , power : int , weights : < built - in function array > = None , X_new : < built - in function array > = None , X_start : int = 0 , X_end : int = 40 , X_num : int = 100 ):
-
- View Source
-
-
-
- 640 def polynomial_regression ( data : pd . DataFrame ,
-641 X_column : str ,
-642 y_column : str ,
-643 power : int ,
-644 weights : np . array = None ,
-645 X_new : np . array = None ,
-646 X_start : int = 0 ,
-647 X_end : int = 40 ,
-648 X_num : int = 100 ):
-649 # !: Weights are not used in this function
-650 X = data [ X_column ] . squeeze () . T
-651 y = data [ y_column ] . squeeze () . T
-652 coef = poly . polyfit ( X , y , power )
-653
-654 if X_new is None :
-655 X_new = np . linspace ( X_start , X_end , num = X_num )
-656
-657 f = poly . polyval ( X_new , coef )
-658
-659 return X_new , f
-
-
-
-
-
-
-
-
-
-
- def
- linear_regression ( data : pandas . core . frame . DataFrame , X_column : str , y_column : str , weights : < built - in function array > = None , return_model : bool = False ) -> tuple [ numpy . array , float , float ] :
-
- View Source
-
-
-
- 662 def linear_regression ( data : pd . DataFrame , X_column : str , y_column : str , weights : np . array = None , return_model : bool = False ) -> tuple [ np . array , float , float ]:
-663 '''Do a linear regression on the data and return the predicted values, the coefficient and the r2 score.'''
-664 X = data [ X_column ] . values . reshape ( - 1 , 1 )
-665 y = data [ y_column ] . values . reshape ( - 1 , 1 )
-666 lr = LinearRegression ()
-667 lr . fit ( X , y , sample_weight = weights )
-668 y_pred = lr . predict ( X )
-669 coef = lr . coef_
-670 r2 = lr . score ( X , y , sample_weight = weights )
-671 if return_model :
-672 return lr
-673 else :
-674 return y_pred , coef , r2
-
-
-
- Do a linear regression on the data and return the predicted values, the coefficient and the r2 score.
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/src/data/read.html b/docs/src/data/read.html
deleted file mode 100644
index d5d8961..0000000
--- a/docs/src/data/read.html
+++ /dev/null
@@ -1,482 +0,0 @@
-
-
-
-
-
-
- src.data.read API documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- View Source
-
- 1 import pandas as pd
- 2 import os
- 3 import numpy as np
- 4 import json
- 5
- 6
- 7 def read_asset_damage ( country ) -> None :
- 8 '''Read asset damage for all districts from a XLSX file and load it into the memory.'''
- 9 if country == 'Saint Lucia' :
-10 all_damage = pd . read_excel (
-11 f "../data/processed/asset_damage/ { country } / { country } .xlsx" , index_col = None , header = 0 )
-12 else :
-13 raise ValueError ( 'Only `Saint Lucia` is supported.' )
-14
-15 return all_damage
-16
-17
-18 def get_asset_damage ( all_damage : pd . DataFrame , scale : str , district : str , return_period : int , print_statistics : bool ) -> tuple :
-19 '''Get asset damage for a specific district.
-20
-21 Args:
-22 all_damage (pd.DataFrame): Asset damage data for all districts.
-23 scale (str): Scale of the analysis. Only `district` is supported.
-24 district (str): District name.
-25 return_period (int): Return period.
-26 print_statistics (bool): Print the statistics.
-27
-28 Returns:
-29 tuple: Event damage, total asset stock, expected loss fraction.
-30
-31 Raises:
-32 ValueError: If the scale is not `district`.
-33 ValueError: If the expected loss fraction is greater than 1.
-34 '''
-35 if scale == 'district' :
-36 event_damage = all_damage . loc [( all_damage [ scale ] == district ) & (
-37 all_damage [ 'rp' ] == return_period ), 'pml' ] . values [ 0 ] # PML
-38 total_asset_stock = all_damage . loc [( all_damage [ scale ] == district ) & (
-39 all_damage [ 'rp' ] == return_period ), 'exposed_value' ] . values [ 0 ] # Exposed value
-40
-41 else :
-42 raise ValueError (
-43 'Only `district` scale is supported.' )
-44
-45 event_damage = event_damage
-46 total_asset_stock = total_asset_stock
-47 expected_loss_fraction = event_damage / total_asset_stock
-48
-49 if expected_loss_fraction > 1 :
-50 raise ValueError (
-51 'Expected loss fraction is greater than 1. Check the data.' )
-52
-53 if print_statistics :
-54 print ( 'Event damage = ' + str ( ' {:,} ' . format ( round ( event_damage ))))
-55 print ( 'Total asset stock = ' +
-56 str ( ' {:,} ' . format ( round ( total_asset_stock ))))
-57 print ( 'Expected loss fraction = ' +
-58 str ( np . round ( expected_loss_fraction , 3 )))
-59
-60 return event_damage , total_asset_stock , expected_loss_fraction
-61
-62
-63 def read_household_survey ( country : str ) -> pd . DataFrame :
-64 '''Reads household survey from a CSV file.
-65
-66 Args:
-67 country (str): Country name.
-68
-69 Returns:
-70 pd.DataFrame: Household survey data.
-71
-72 Raises:
-73 ValueError: If the country is not `Saint Lucia`.
-74 '''
-75 if country == 'Saint Lucia' :
-76 household_survey = pd . read_csv (
-77 f "../data/processed/household_survey/ { country } / { country } .csv" )
-78 else :
-79 raise ValueError ( 'Only `Saint Lucia` is supported.' )
-80
-81 return household_survey
-
-
-
-
-
-
-
-
- def
- read_asset_damage (country ) -> None :
-
- View Source
-
-
-
- 8 def read_asset_damage ( country ) -> None :
- 9 '''Read asset damage for all districts from a XLSX file and load it into the memory.'''
-10 if country == 'Saint Lucia' :
-11 all_damage = pd . read_excel (
-12 f "../data/processed/asset_damage/ { country } / { country } .xlsx" , index_col = None , header = 0 )
-13 else :
-14 raise ValueError ( 'Only `Saint Lucia` is supported.' )
-15
-16 return all_damage
-
-
-
- Read asset damage for all districts from a XLSX file and load it into the memory.
-
-
-
-
-
-
-
-
- def
- get_asset_damage ( all_damage : pandas . core . frame . DataFrame , scale : str , district : str , return_period : int , print_statistics : bool ) -> tuple :
-
- View Source
-
-
-
- 19 def get_asset_damage ( all_damage : pd . DataFrame , scale : str , district : str , return_period : int , print_statistics : bool ) -> tuple :
-20 '''Get asset damage for a specific district.
-21
-22 Args:
-23 all_damage (pd.DataFrame): Asset damage data for all districts.
-24 scale (str): Scale of the analysis. Only `district` is supported.
-25 district (str): District name.
-26 return_period (int): Return period.
-27 print_statistics (bool): Print the statistics.
-28
-29 Returns:
-30 tuple: Event damage, total asset stock, expected loss fraction.
-31
-32 Raises:
-33 ValueError: If the scale is not `district`.
-34 ValueError: If the expected loss fraction is greater than 1.
-35 '''
-36 if scale == 'district' :
-37 event_damage = all_damage . loc [( all_damage [ scale ] == district ) & (
-38 all_damage [ 'rp' ] == return_period ), 'pml' ] . values [ 0 ] # PML
-39 total_asset_stock = all_damage . loc [( all_damage [ scale ] == district ) & (
-40 all_damage [ 'rp' ] == return_period ), 'exposed_value' ] . values [ 0 ] # Exposed value
-41
-42 else :
-43 raise ValueError (
-44 'Only `district` scale is supported.' )
-45
-46 event_damage = event_damage
-47 total_asset_stock = total_asset_stock
-48 expected_loss_fraction = event_damage / total_asset_stock
-49
-50 if expected_loss_fraction > 1 :
-51 raise ValueError (
-52 'Expected loss fraction is greater than 1. Check the data.' )
-53
-54 if print_statistics :
-55 print ( 'Event damage = ' + str ( ' {:,} ' . format ( round ( event_damage ))))
-56 print ( 'Total asset stock = ' +
-57 str ( ' {:,} ' . format ( round ( total_asset_stock ))))
-58 print ( 'Expected loss fraction = ' +
-59 str ( np . round ( expected_loss_fraction , 3 )))
-60
-61 return event_damage , total_asset_stock , expected_loss_fraction
-
-
-
- Get asset damage for a specific district.
-
-
Args:
- all_damage (pd.DataFrame): Asset damage data for all districts.
- scale (str): Scale of the analysis. Only district
is supported.
- district (str): District name.
- return_period (int): Return period.
- print_statistics (bool): Print the statistics.
-
-
Returns:
- tuple: Event damage, total asset stock, expected loss fraction.
-
-
Raises:
- ValueError: If the scale is not district
.
- ValueError: If the expected loss fraction is greater than 1.
-
-
-
-
-
-
-
-
- def
- read_household_survey (country : str ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 64 def read_household_survey ( country : str ) -> pd . DataFrame :
-65 '''Reads household survey from a CSV file.
-66
-67 Args:
-68 country (str): Country name.
-69
-70 Returns:
-71 pd.DataFrame: Household survey data.
-72
-73 Raises:
-74 ValueError: If the country is not `Saint Lucia`.
-75 '''
-76 if country == 'Saint Lucia' :
-77 household_survey = pd . read_csv (
-78 f "../data/processed/household_survey/ { country } / { country } .csv" )
-79 else :
-80 raise ValueError ( 'Only `Saint Lucia` is supported.' )
-81
-82 return household_survey
-
-
-
- Reads household survey from a CSV file.
-
-
Args:
- country (str): Country name.
-
-
Returns:
- pd.DataFrame: Household survey data.
-
-
Raises:
- ValueError: If the country is not Saint Lucia
.
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/src/data/visualise.html b/docs/src/data/visualise.html
deleted file mode 100644
index a7f4260..0000000
--- a/docs/src/data/visualise.html
+++ /dev/null
@@ -1,1190 +0,0 @@
-
-
-
-
-
-
- src.data.visualise API documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- View Source
-
- 1 import geopandas as gpd
- 2 import matplotlib
- 3 import matplotlib.pyplot as plt
- 4 import pandas as pd
- 5 import numpy as np
- 6 from sklearn.preprocessing import MinMaxScaler
- 7 import ptitprince as pt
- 8 import seaborn as sns
- 9 from scipy.stats import spearmanr
- 10 from matplotlib.ticker import MaxNLocator
- 11 # import contextily as ctx
- 12
- 13
- 14 def rainclouds ( outcomes : pd . DataFrame , savefigs : bool , x_columns : list = [], x_titles : list = [], plot_years_in_poverty : bool = False , color_palette : str = 'Set2' , sharex : bool = True ):
- 15 districts = outcomes [ 'district' ] . unique () . tolist ()
- 16 n_districts = len ( districts )
- 17 colors = sns . color_palette ( color_palette , n_colors = len ( districts ))
- 18
- 19 if len ( x_columns ) == 0 :
- 20 x_columns = [
- 21 'n_affected_people' ,
- 22 'n_new_poor_increase_pct' ,
- 23 'n_new_poor' ,
- 24 'annual_average_consumption_loss_pct' ,
- 25 'r' ,
- 26 'new_poverty_gap' ,
- 27 # 'one_year_in_poverty',
- 28 # 'two_years_in_poverty',
- 29 # 'three_years_in_poverty',
- 30 # 'four_years_in_poverty',
- 31 # 'five_years_in_poverty',
- 32 # 'six_years_in_poverty',
- 33 # 'seven_years_in_poverty',
- 34 # 'eight_years_in_poverty',
- 35 # 'nine_years_in_poverty',
- 36 # 'ten_years_in_poverty'
- 37 ]
- 38
- 39 if len ( x_titles ) == 0 :
- 40 x_titles = [
- 41 'Affected People' ,
- 42 'New Poor Increase (%)' ,
- 43 'New Poor' ,
- 44 'Wt. Ann. Avg. Consump. Loss p.c. (%)' ,
- 45 'Socio-Economic Resilience' ,
- 46 'Poverty Gap' ,
- 47 # 'One year in poverty',
- 48 # 'Two years in poverty',
- 49 # 'Three years in poverty',
- 50 # 'Four years in poverty',
- 51 # 'Five years in poverty',
- 52 # 'Six years in poverty',
- 53 # 'Seven years in poverty',
- 54 # 'Eight years in poverty',
- 55 # 'Nine years in poverty',
- 56 # 'Ten years in poverty'
- 57 ]
- 58
- 59 is_years_in_poverty = False
- 60
- 61 for x_column , x_title in zip ( x_columns , x_titles ):
- 62 fig , ax = plt . subplots ( ncols = 3 , nrows = 3 , figsize = (
- 63 4 * n_districts / 3 , 3 * n_districts / 3 ), sharex = sharex )
- 64
- 65 for district in districts :
- 66 df = outcomes [ outcomes [ 'district' ] == district ] . copy ()
- 67
- 68 # Calculate an increase in new poor in respect to the total population
- 69 # df = df.assign(one_year_in_poverty = df['years_in_poverty'].apply(lambda x: x[0]))
- 70 # df = df.assign(two_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[1]))
- 71 # df = df.assign(three_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[2]))
- 72 # df = df.assign(four_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[3]))
- 73 # df = df.assign(five_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[4]))
- 74 # df = df.assign(six_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[5]))
- 75 # df = df.assign(seven_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[6]))
- 76 # df = df.assign(eight_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[7]))
- 77 # df = df.assign(nine_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[8]))
- 78 # df = df.assign(ten_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[9]))
- 79
- 80 df [ x_column ] = df [ x_column ] . astype ( float )
- 81
- 82 # Make a half violin plot
- 83 pt . half_violinplot ( x = x_column ,
- 84 y = 'policy' , # hue='scenario',
- 85 data = df ,
- 86 color = colors [ districts . index ( district )],
- 87 bw = .2 ,
- 88 cut = 0. ,
- 89 scale = "area" ,
- 90 width = .6 ,
- 91 inner = None ,
- 92 ax = ax [ districts . index ( district ) // 3 , districts . index ( district ) % 3 ])
- 93
- 94 # Add stripplot
- 95 sns . stripplot ( x = x_column ,
- 96 y = 'policy' , # hue='scenario',
- 97 data = df ,
- 98 color = colors [ districts . index ( district )],
- 99 edgecolor = 'white' ,
-100 size = 3 ,
-101 jitter = 1 ,
-102 zorder = 0 ,
-103 orient = 'h' ,
-104 ax = ax [ districts . index ( district ) // 3 , districts . index ( district ) % 3 ])
-105
-106 # Add boxplot
-107 sns . boxplot ( x = x_column ,
-108 y = 'policy' , # hue='scenario',
-109 data = df ,
-110 color = "black" ,
-111 width = .15 ,
-112 zorder = 10 ,
-113 showcaps = True ,
-114 boxprops = { 'facecolor' : 'none' , "zorder" : 10 },
-115 showfliers = True ,
-116 whiskerprops = { 'linewidth' : 2 , "zorder" : 10 },
-117 saturation = 1 ,
-118 orient = 'h' ,
-119 ax = ax [ districts . index ( district ) // 3 , districts . index ( district ) % 3 ])
-120
-121 if is_years_in_poverty :
-122 title = district + ', E = ' + \
-123 f ' { round ( df [ x_column ] . mean ()) } '
-124 else :
-125 title = district
-126 ax [ districts . index ( district ) // 3 ,
-127 districts . index ( district ) % 3 ] . set_title ( title )
-128 ax [ districts . index ( district ) // 3 ,
-129 districts . index ( district ) % 3 ] . set_ylabel ( '' )
-130 ax [ districts . index ( district ) // 3 ,
-131 districts . index ( district ) % 3 ] . set_xlabel ( x_title )
-132
-133 # Remove y ticks and labels
-134 ax [ districts . index ( district ) // 3 ,
-135 districts . index ( district ) % 3 ] . set_yticklabels ([])
-136 ax [ districts . index ( district ) // 3 ,
-137 districts . index ( district ) % 3 ] . set_yticks ([])
-138
-139 # Do not display floats in the x-axis
-140 ax [ districts . index ( district ) // 3 , districts . index ( district ) %
-141 3 ] . xaxis . set_major_locator ( MaxNLocator ( integer = True ))
-142
-143 # Plot the median
-144 # ax[districts.index(district) // 3, districts.index(district) % 3].axvline(df[x_column].median(), color='black', linestyle='--', linewidth=1)
-145
-146 # Add text close to the boxplot's median
-147 ax [ districts . index ( district ) // 3 , districts . index ( district ) % 3 ] . text ( df [ x_column ] . median (), 0.2 ,
-148 f 'M= { df [ x_column ] . median () : .2f } ' ,
-149 horizontalalignment = 'left' , size = 'small' , color = 'black' )
-150
-151 # # Add text close to the boxplot's min and max
-152 # ax[districts.index(district) // 3, districts.index(district) % 3].text(df[x_column].min(), 0.3,
-153 # f'min={df[x_column].min():.2f}',
-154 # horizontalalignment='left', size='small', color='black')
-155 # ax[districts.index(district) // 3, districts.index(district) % 3].text(df[x_column].max(), 0.4,
-156 # f'max={df[x_column].max():.2f}',
-157 # horizontalalignment='left', size='small', color='black')
-158
-159 initial_poverty_gap = df [ 'initial_poverty_gap' ] . iloc [ 0 ]
-160
-161 # Add initial poverty gap as in the legend to the plot
-162 if x_column == 'new_poverty_gap' :
-163 ax [ districts . index ( district ) // 3 , districts . index ( district ) % 3 ] . text ( 0.025 , 0.9 ,
-164 f 'Poverty gap before disaster= { initial_poverty_gap : .2f } ' ,
-165 horizontalalignment = 'left' , size = 'small' , color = 'black' ,
-166 transform = ax [ districts . index ( district ) // 3 , districts . index ( district ) % 3 ] . transAxes )
-167
-168 # Add a super title
-169 # fig.suptitle(x_title, fontsize=16)
-170 fig . tight_layout ()
-171 if savefigs :
-172 plt . savefig (
-173 f '../figures/analysis/ { x_column } .png' , dpi = 500 , bbox_inches = 'tight' )
-174
-175
-176 def bivariate_choropleth ( data , x_name , y_name , x_label , y_label , scale , figsize , return_table ):
-177 fig , ax = plt . subplots ( figsize = figsize )
-178
-179 # Bin the data
-180 data = bin_data ( data , x_name , y_name , scale , print_statistics = False )
-181
-182 # Get colors
-183 all_colors , available_colors = get_colors ( data )
-184 cmap = matplotlib . colors . ListedColormap ( available_colors )
-185
-186 # Step 1: Draw the map
-187 # border = gpd.read_file(f'../data/processed/boundaries/{city}/city.json')
-188 border = gpd . read_file (
-189 '../data/raw/shapefiles/Saint Lucia/gadm36_LCA_shp/gadm36_LCA_0.shp' )
-190 data . plot ( ax = ax ,
-191 edgecolor = 'black' ,
-192 linewidth = .1 ,
-193 column = 'Bi_Class' , # variable that is going to be used to color the map
-194 cmap = cmap , # newly defined bivariate cmap
-195 categorical = True , # bivariate choropleth has to be colored as categorical map
-196 legend = False ) # we're going to draw the legend ourselves
-197 # add the basemap
-198 # ctx.add_basemap(ax=ax, source=ctx.providers.CartoDB.Positron)
-199 border . plot ( ax = ax , facecolor = 'none' ,
-200 edgecolor = 'black' , alpha = .5 ) # city border
-201 for idx , row in data . iterrows ():
-202 ax . annotate ( text = row [ 'NAME_1' ], xy = row [ 'geometry' ] . centroid . coords [ 0 ],
-203 ha = 'center' , fontsize = 8 , color = 'white' )
-204
-205 plt . tight_layout () # "tighten" two figures map and basemap
-206 plt . axis ( 'off' ) # we don't need axis with coordinates
-207 # ax.set_title('Bivariate Choropleth Amsterdam')
-208
-209 # Step 2: draw the legend
-210
-211 # We're drawing a 3x3 "box" as 3 columns
-212 # The xmin and xmax arguments axvspan are defined to create equally sized small boxes
-213
-214 img2 = fig # refer to the main figure
-215 # add new axes to place the legend there
-216 ax2 = fig . add_axes ([ 0.15 , 0.25 , 0.1 , 0.1 ])
-217 # and specify its location
-218 alpha = 1 # alpha argument to make it more/less transparent
-219
-220 # Column 1
-221 # All colors to create a complete legend
-222 # all_colors = ['#e8e8e8', '#b0d5df', '#64acbe', '#e4acac', '#ad9ea5', '#627f8c', '#c85a5a', '#985356', '#574249']
-223
-224 ax2 . axvspan ( xmin = 0 , xmax = 0.33 , ymin = 0 , ymax = 0.33 ,
-225 alpha = alpha , color = all_colors [ 0 ])
-226 ax2 . axvspan ( xmin = 0 , xmax = 0.33 , ymin = 0.33 , ymax = 0.66 ,
-227 alpha = alpha , color = all_colors [ 1 ])
-228 ax2 . axvspan ( xmin = 0 , xmax = 0.33 , ymin = 0.66 , ymax = 1 ,
-229 alpha = alpha , color = all_colors [ 2 ])
-230
-231 # Column 2
-232 ax2 . axvspan ( xmin = 0.33 , xmax = 0.66 , ymin = 0 , ymax = 0.33 ,
-233 alpha = alpha , color = all_colors [ 3 ])
-234 ax2 . axvspan ( xmin = 0.33 , xmax = 0.66 , ymin = 0.33 , ymax = 0.66 ,
-235 alpha = alpha , color = all_colors [ 4 ])
-236 ax2 . axvspan ( xmin = 0.33 , xmax = 0.66 , ymin = 0.66 , ymax = 1 ,
-237 alpha = alpha , color = all_colors [ 5 ])
-238
-239 # Column 3
-240 ax2 . axvspan ( xmin = 0.66 , xmax = 1 , ymin = 0 , ymax = 0.33 ,
-241 alpha = alpha , color = all_colors [ 6 ])
-242 ax2 . axvspan ( xmin = 0.66 , xmax = 1 , ymin = 0.33 , ymax = 0.66 ,
-243 alpha = alpha , color = all_colors [ 7 ])
-244 ax2 . axvspan ( xmin = 0.66 , xmax = 1 , ymin = 0.66 , ymax = 1 ,
-245 alpha = alpha , color = all_colors [ 8 ])
-246
-247 # Step 3: annoate the legend
-248 # remove ticks from the big box
-249 ax2 . tick_params ( axis = 'both' , which = 'both' , length = 0 )
-250 ax2 . axis ( 'off' ) # turn off its axis
-251 ax2 . annotate ( "" , xy = ( 0 , 1 ), xytext = ( 0 , 0 ), arrowprops = dict (
-252 arrowstyle = "->" , lw = 1 , color = 'black' )) # draw arrow for x
-253 ax2 . annotate ( "" , xy = ( 1 , 0 ), xytext = ( 0 , 0 ), arrowprops = dict (
-254 arrowstyle = "->" , lw = 1 , color = 'black' )) # draw arrow for y
-255 ax2 . text ( s = x_label , x = 0.1 , y =- 0.25 , fontsize = 8 ) # annotate x axis
-256 ax2 . text ( s = y_label , x =- 0.25 , y = 0.1 , rotation = 90 ,
-257 fontsize = 8 ) # annotate y axis
-258 # plt.savefig('bivariate_choropleth.png', dpi=300)
-259
-260 if return_table :
-261 return data
-262
-263
-264 def nine_quadrants_plot ( data , x_name , y_name , scale = True ):
-265 _ , ax = plt . subplots ( figsize = ( 6 , 5 ))
-266
-267 if scale :
-268 scaler = MinMaxScaler ()
-269 # data[x_name] = scaler.fit_transform(data[x_name].values.reshape(-1, 1))
-270 # data[y_name] = scaler.fit_transform(data[y_name].values.reshape(-1, 1))
-271 # Scale data between 0 and 1
-272 data [ x_name ] = ( data [ x_name ] - data [ x_name ] . min ()) / \
-273 ( data [ x_name ] . max () - data [ x_name ] . min ())
-274 data [ y_name ] = ( data [ y_name ] - data [ y_name ] . min ()) / \
-275 ( data [ y_name ] . max () - data [ y_name ] . min ())
-276
-277 data . plot . scatter ( x_name , y_name , s = 20 , ax = ax , c = 'black' , zorder = 2 )
-278
-279 # Iterate over each row and annotate the points
-280 for idx , row in data . iterrows ():
-281 ax . annotate ( text = row [ 'NAME_1' ], xy = ( row [ x_name ], row [ y_name ]),
-282 ha = 'center' , fontsize = 10 , color = 'black' )
-283
-284 # Annotate with Spearman's rho
-285 # rho, p = spearmanr(data[x_name], data[y_name])
-286 # ax.text(0.05, 0.95, f'$\\rho$ = {round(rho, 2)}', transform=ax.transAxes,
-287 # verticalalignment='top', fontsize=12, bbox=dict(facecolor='white', edgecolor='black', alpha=1))
-288
-289 ax . axvline ( 0.33 , color = 'black' , alpha = .33 , lw = 1 )
-290 ax . axvline ( 0.66 , color = 'black' , alpha = .33 , lw = 1 )
-291 ax . axhline ( 0.33 , color = 'black' , alpha = .33 , lw = 1 )
-292 ax . axhline ( 0.66 , color = 'black' , alpha = .33 , lw = 1 )
-293
-294 alpha = 1
-295
-296 all_colors = { '1A' : '#dddddd' ,
-297 '1B' : '#dd7c8a' ,
-298 '1C' : '#cc0024' ,
-299 '2A' : '#7bb3d1' ,
-300 '2B' : '#8d6c8f' ,
-301 '2C' : '#8a274a' ,
-302 '3A' : '#016eae' ,
-303 '3B' : '#4a4779' ,
-304 '3C' : '#4b264d' }
-305
-306 # Column 1
-307 c = all_colors [ '1A' ]
-308 ax . axvspan ( xmin = 0 , xmax = 0.33 , ymin = 0 + 0.025 ,
-309 ymax = 0.345 , alpha = alpha , color = c )
-310
-311 c = all_colors [ '1B' ]
-312 ax . axvspan ( xmin = 0 , xmax = 0.33 , ymin = 0.33 + 0.015 ,
-313 ymax = 0.66 - 0.015 , alpha = alpha , color = c )
-314
-315 c = all_colors [ '1C' ]
-316 ax . axvspan ( xmin = 0 , xmax = 0.33 , ymin = 0.66 - 0.015 ,
-317 ymax = 1 - 0.05 , alpha = alpha , color = c )
-318
-319 # Column 2
-320 c = all_colors [ '2A' ]
-321 ax . axvspan ( xmin = 0.33 , xmax = 0.66 , ymin = 0 + 0.025 ,
-322 ymax = 0.345 , alpha = alpha , color = c )
-323
-324 c = all_colors [ '2B' ]
-325 ax . axvspan ( xmin = 0.33 , xmax = 0.66 , ymin = 0.345 ,
-326 ymax = 0.645 , alpha = alpha , color = c )
-327
-328 c = all_colors [ '2C' ]
-329 ax . axvspan ( xmin = 0.33 , xmax = 0.66 , ymin = 0.649 ,
-330 ymax = 1 - 0.05 , alpha = alpha , color = c )
-331
-332 # Column 3
-333 c = all_colors [ '3A' ]
-334 ax . axvspan ( xmin = 0.66 , xmax = 1 , ymin = 0.025 , ymax = 0.345 , alpha = alpha , color = c )
-335
-336 c = all_colors [ '3B' ]
-337 ax . axvspan ( xmin = 0.66 , xmax = 1 , ymin = 0.345 ,
-338 ymax = 0.645 , alpha = alpha , color = c )
-339
-340 c = all_colors [ '3C' ]
-341 ax . axvspan ( xmin = 0.66 , xmax = 1 , ymin = 0.649 ,
-342 ymax = 1 - 0.05 , alpha = alpha , color = c )
-343
-344 ax . set_xlim ( - .05 , 1.05 )
-345 ax . set_ylim ( - 0.05 , 1.05 )
-346
-347 # Add regression line
-348 # x = data[x_name]
-349 # y = data[y_name]
-350 # m, b = np.polyfit(x, y, 1)
-351 # ax.plot(x, m * x + b, color='black', alpha=0.5, zorder=1)
-352
-353
-354 def get_colors ( data ):
-355
-356 # colors = ['#e8e8e8', # 1A
-357 # '#b0d5df', # 1B
-358 # # '#64acbe', # 1C
-359 # '#e4acac', # 2A
-360 # '#ad9ea5', # 2B
-361 # '#627f8c', # 2C
-362 # '#c85a5a', # 3A
-363 # '#985356'] # , # 3B
-364 # # '#574249'] # 3C
-365
-366 all_colors = { '1A' : '#e8e8e8' ,
-367 '1B' : '#b0d5df' ,
-368 '1C' : '#64acbe' ,
-369 '2A' : '#e4acac' ,
-370 '2B' : '#ad9ea5' ,
-371 '2C' : '#627f8c' ,
-372 '3A' : '#c85a5a' ,
-373 '3B' : '#985356' ,
-374 '3C' : '#574249' }
-375
-376 all_colors = { '1A' : '#dddddd' ,
-377 '1B' : '#dd7c8a' ,
-378 '1C' : '#cc0024' ,
-379 '2A' : '#7bb3d1' ,
-380 '2B' : '#8d6c8f' ,
-381 '2C' : '#8a274a' ,
-382 '3A' : '#016eae' ,
-383 '3B' : '#4a4779' ,
-384 '3C' : '#4b264d' }
-385
-386 # Set of colors matching the elements of Bi_Class
-387 # We have to exclude those that did not come up in the data
-388 available_classes = data [ 'Bi_Class' ] . value_counts () . sort_index () . index
-389 available_colors = [ all_colors [ i ] for i in available_classes ]
-390 return list ( all_colors . values ()), available_colors
-391
-392
-393 def bin_data ( data , x_name , y_name , scale , print_statistics = True ):
-394 if scale :
-395 # Scale the data to be between 0 and 1
-396 # data[x_name] = (data[x_name] - data[x_name].min()) / \
-397 # (data[x_name].max() - data[x_name].min())
-398 # data[y_name] = (data[y_name] - data[y_name].min()) / \
-399 # (data[y_name].max() - data[y_name].min())
-400 # Scale the data with MinMaxScaler
-401 scaler = MinMaxScaler ()
-402 data [ x_name ] = scaler . fit_transform ( data [ x_name ] . values . reshape ( - 1 , 1 ))
-403 data [ y_name ] = scaler . fit_transform ( data [ y_name ] . values . reshape ( - 1 , 1 ))
-404
-405 # Define the bins
-406 bins = [ 0 , 0.33 , 0.66 , 1 ]
-407
-408 # Bin the first variable - x
-409 data [ 'Var1_Class' ] = pd . cut ( data [ x_name ], bins = bins , include_lowest = True )
-410 data [ 'Var1_Class' ] = data [ 'Var1_Class' ] . astype ( 'str' )
-411
-412 # Bin the second variable - y
-413 data [ 'Var2_Class' ] = pd . cut ( data [ y_name ], bins = bins , include_lowest = True )
-414 data [ 'Var2_Class' ] = data [ 'Var2_Class' ] . astype ( 'str' )
-415
-416 # Code created x bins to 1, 2, 3
-417 x_class_codes = np . arange ( 1 , len ( bins ))
-418 d = dict (
-419 zip ( data [ 'Var1_Class' ] . value_counts () . sort_index () . index , x_class_codes ))
-420 data [ 'Var1_Class' ] = data [ 'Var1_Class' ] . replace ( d )
-421
-422 # Code created y bins to A, B, C
-423 y_class_codes = [ 'A' , 'B' , 'C' ]
-424 d = dict (
-425 zip ( data [ 'Var2_Class' ] . value_counts () . sort_index () . index , y_class_codes ))
-426 data [ 'Var2_Class' ] = data [ 'Var2_Class' ] . replace ( d )
-427
-428 # Combine x and y codes to create Bi_Class
-429 data [ 'Bi_Class' ] = data [ 'Var1_Class' ] . astype ( 'str' ) + data [ 'Var2_Class' ]
-430
-431 if print_statistics :
-432 print ( 'Number of unique elements in Var1_Class =' ,
-433 len ( data [ 'Var1_Class' ] . unique ()))
-434 print ( 'Number of unique elements in Var2_Class =' ,
-435 len ( data [ 'Var2_Class' ] . unique ()))
-436 print ( 'Number of unique elements in Bi_Class =' ,
-437 len ( data [ 'Bi_Class' ] . unique ()))
-438 return data
-
-
-
-
-
-
-
-
- def
- rainclouds ( outcomes : pandas . core . frame . DataFrame , savefigs : bool , x_columns : list = [] , x_titles : list = [] , plot_years_in_poverty : bool = False , color_palette : str = 'Set2' , sharex : bool = True ):
-
- View Source
-
-
-
- 15 def rainclouds ( outcomes : pd . DataFrame , savefigs : bool , x_columns : list = [], x_titles : list = [], plot_years_in_poverty : bool = False , color_palette : str = 'Set2' , sharex : bool = True ):
- 16 districts = outcomes [ 'district' ] . unique () . tolist ()
- 17 n_districts = len ( districts )
- 18 colors = sns . color_palette ( color_palette , n_colors = len ( districts ))
- 19
- 20 if len ( x_columns ) == 0 :
- 21 x_columns = [
- 22 'n_affected_people' ,
- 23 'n_new_poor_increase_pct' ,
- 24 'n_new_poor' ,
- 25 'annual_average_consumption_loss_pct' ,
- 26 'r' ,
- 27 'new_poverty_gap' ,
- 28 # 'one_year_in_poverty',
- 29 # 'two_years_in_poverty',
- 30 # 'three_years_in_poverty',
- 31 # 'four_years_in_poverty',
- 32 # 'five_years_in_poverty',
- 33 # 'six_years_in_poverty',
- 34 # 'seven_years_in_poverty',
- 35 # 'eight_years_in_poverty',
- 36 # 'nine_years_in_poverty',
- 37 # 'ten_years_in_poverty'
- 38 ]
- 39
- 40 if len ( x_titles ) == 0 :
- 41 x_titles = [
- 42 'Affected People' ,
- 43 'New Poor Increase (%)' ,
- 44 'New Poor' ,
- 45 'Wt. Ann. Avg. Consump. Loss p.c. (%)' ,
- 46 'Socio-Economic Resilience' ,
- 47 'Poverty Gap' ,
- 48 # 'One year in poverty',
- 49 # 'Two years in poverty',
- 50 # 'Three years in poverty',
- 51 # 'Four years in poverty',
- 52 # 'Five years in poverty',
- 53 # 'Six years in poverty',
- 54 # 'Seven years in poverty',
- 55 # 'Eight years in poverty',
- 56 # 'Nine years in poverty',
- 57 # 'Ten years in poverty'
- 58 ]
- 59
- 60 is_years_in_poverty = False
- 61
- 62 for x_column , x_title in zip ( x_columns , x_titles ):
- 63 fig , ax = plt . subplots ( ncols = 3 , nrows = 3 , figsize = (
- 64 4 * n_districts / 3 , 3 * n_districts / 3 ), sharex = sharex )
- 65
- 66 for district in districts :
- 67 df = outcomes [ outcomes [ 'district' ] == district ] . copy ()
- 68
- 69 # Calculate an increase in new poor in respect to the total population
- 70 # df = df.assign(one_year_in_poverty = df['years_in_poverty'].apply(lambda x: x[0]))
- 71 # df = df.assign(two_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[1]))
- 72 # df = df.assign(three_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[2]))
- 73 # df = df.assign(four_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[3]))
- 74 # df = df.assign(five_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[4]))
- 75 # df = df.assign(six_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[5]))
- 76 # df = df.assign(seven_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[6]))
- 77 # df = df.assign(eight_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[7]))
- 78 # df = df.assign(nine_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[8]))
- 79 # df = df.assign(ten_years_in_poverty = df['years_in_poverty'].apply(lambda x: x[9]))
- 80
- 81 df [ x_column ] = df [ x_column ] . astype ( float )
- 82
- 83 # Make a half violin plot
- 84 pt . half_violinplot ( x = x_column ,
- 85 y = 'policy' , # hue='scenario',
- 86 data = df ,
- 87 color = colors [ districts . index ( district )],
- 88 bw = .2 ,
- 89 cut = 0. ,
- 90 scale = "area" ,
- 91 width = .6 ,
- 92 inner = None ,
- 93 ax = ax [ districts . index ( district ) // 3 , districts . index ( district ) % 3 ])
- 94
- 95 # Add stripplot
- 96 sns . stripplot ( x = x_column ,
- 97 y = 'policy' , # hue='scenario',
- 98 data = df ,
- 99 color = colors [ districts . index ( district )],
-100 edgecolor = 'white' ,
-101 size = 3 ,
-102 jitter = 1 ,
-103 zorder = 0 ,
-104 orient = 'h' ,
-105 ax = ax [ districts . index ( district ) // 3 , districts . index ( district ) % 3 ])
-106
-107 # Add boxplot
-108 sns . boxplot ( x = x_column ,
-109 y = 'policy' , # hue='scenario',
-110 data = df ,
-111 color = "black" ,
-112 width = .15 ,
-113 zorder = 10 ,
-114 showcaps = True ,
-115 boxprops = { 'facecolor' : 'none' , "zorder" : 10 },
-116 showfliers = True ,
-117 whiskerprops = { 'linewidth' : 2 , "zorder" : 10 },
-118 saturation = 1 ,
-119 orient = 'h' ,
-120 ax = ax [ districts . index ( district ) // 3 , districts . index ( district ) % 3 ])
-121
-122 if is_years_in_poverty :
-123 title = district + ', E = ' + \
-124 f ' { round ( df [ x_column ] . mean ()) } '
-125 else :
-126 title = district
-127 ax [ districts . index ( district ) // 3 ,
-128 districts . index ( district ) % 3 ] . set_title ( title )
-129 ax [ districts . index ( district ) // 3 ,
-130 districts . index ( district ) % 3 ] . set_ylabel ( '' )
-131 ax [ districts . index ( district ) // 3 ,
-132 districts . index ( district ) % 3 ] . set_xlabel ( x_title )
-133
-134 # Remove y ticks and labels
-135 ax [ districts . index ( district ) // 3 ,
-136 districts . index ( district ) % 3 ] . set_yticklabels ([])
-137 ax [ districts . index ( district ) // 3 ,
-138 districts . index ( district ) % 3 ] . set_yticks ([])
-139
-140 # Do not display floats in the x-axis
-141 ax [ districts . index ( district ) // 3 , districts . index ( district ) %
-142 3 ] . xaxis . set_major_locator ( MaxNLocator ( integer = True ))
-143
-144 # Plot the median
-145 # ax[districts.index(district) // 3, districts.index(district) % 3].axvline(df[x_column].median(), color='black', linestyle='--', linewidth=1)
-146
-147 # Add text close to the boxplot's median
-148 ax [ districts . index ( district ) // 3 , districts . index ( district ) % 3 ] . text ( df [ x_column ] . median (), 0.2 ,
-149 f 'M= { df [ x_column ] . median () : .2f } ' ,
-150 horizontalalignment = 'left' , size = 'small' , color = 'black' )
-151
-152 # # Add text close to the boxplot's min and max
-153 # ax[districts.index(district) // 3, districts.index(district) % 3].text(df[x_column].min(), 0.3,
-154 # f'min={df[x_column].min():.2f}',
-155 # horizontalalignment='left', size='small', color='black')
-156 # ax[districts.index(district) // 3, districts.index(district) % 3].text(df[x_column].max(), 0.4,
-157 # f'max={df[x_column].max():.2f}',
-158 # horizontalalignment='left', size='small', color='black')
-159
-160 initial_poverty_gap = df [ 'initial_poverty_gap' ] . iloc [ 0 ]
-161
-162 # Add initial poverty gap as in the legend to the plot
-163 if x_column == 'new_poverty_gap' :
-164 ax [ districts . index ( district ) // 3 , districts . index ( district ) % 3 ] . text ( 0.025 , 0.9 ,
-165 f 'Poverty gap before disaster= { initial_poverty_gap : .2f } ' ,
-166 horizontalalignment = 'left' , size = 'small' , color = 'black' ,
-167 transform = ax [ districts . index ( district ) // 3 , districts . index ( district ) % 3 ] . transAxes )
-168
-169 # Add a super title
-170 # fig.suptitle(x_title, fontsize=16)
-171 fig . tight_layout ()
-172 if savefigs :
-173 plt . savefig (
-174 f '../figures/analysis/ { x_column } .png' , dpi = 500 , bbox_inches = 'tight' )
-
-
-
-
-
-
-
-
-
-
- def
- bivariate_choropleth (data , x_name , y_name , x_label , y_label , scale , figsize , return_table ):
-
- View Source
-
-
-
- 177 def bivariate_choropleth ( data , x_name , y_name , x_label , y_label , scale , figsize , return_table ):
-178 fig , ax = plt . subplots ( figsize = figsize )
-179
-180 # Bin the data
-181 data = bin_data ( data , x_name , y_name , scale , print_statistics = False )
-182
-183 # Get colors
-184 all_colors , available_colors = get_colors ( data )
-185 cmap = matplotlib . colors . ListedColormap ( available_colors )
-186
-187 # Step 1: Draw the map
-188 # border = gpd.read_file(f'../data/processed/boundaries/{city}/city.json')
-189 border = gpd . read_file (
-190 '../data/raw/shapefiles/Saint Lucia/gadm36_LCA_shp/gadm36_LCA_0.shp' )
-191 data . plot ( ax = ax ,
-192 edgecolor = 'black' ,
-193 linewidth = .1 ,
-194 column = 'Bi_Class' , # variable that is going to be used to color the map
-195 cmap = cmap , # newly defined bivariate cmap
-196 categorical = True , # bivariate choropleth has to be colored as categorical map
-197 legend = False ) # we're going to draw the legend ourselves
-198 # add the basemap
-199 # ctx.add_basemap(ax=ax, source=ctx.providers.CartoDB.Positron)
-200 border . plot ( ax = ax , facecolor = 'none' ,
-201 edgecolor = 'black' , alpha = .5 ) # city border
-202 for idx , row in data . iterrows ():
-203 ax . annotate ( text = row [ 'NAME_1' ], xy = row [ 'geometry' ] . centroid . coords [ 0 ],
-204 ha = 'center' , fontsize = 8 , color = 'white' )
-205
-206 plt . tight_layout () # "tighten" two figures map and basemap
-207 plt . axis ( 'off' ) # we don't need axis with coordinates
-208 # ax.set_title('Bivariate Choropleth Amsterdam')
-209
-210 # Step 2: draw the legend
-211
-212 # We're drawing a 3x3 "box" as 3 columns
-213 # The xmin and xmax arguments axvspan are defined to create equally sized small boxes
-214
-215 img2 = fig # refer to the main figure
-216 # add new axes to place the legend there
-217 ax2 = fig . add_axes ([ 0.15 , 0.25 , 0.1 , 0.1 ])
-218 # and specify its location
-219 alpha = 1 # alpha argument to make it more/less transparent
-220
-221 # Column 1
-222 # All colors to create a complete legend
-223 # all_colors = ['#e8e8e8', '#b0d5df', '#64acbe', '#e4acac', '#ad9ea5', '#627f8c', '#c85a5a', '#985356', '#574249']
-224
-225 ax2 . axvspan ( xmin = 0 , xmax = 0.33 , ymin = 0 , ymax = 0.33 ,
-226 alpha = alpha , color = all_colors [ 0 ])
-227 ax2 . axvspan ( xmin = 0 , xmax = 0.33 , ymin = 0.33 , ymax = 0.66 ,
-228 alpha = alpha , color = all_colors [ 1 ])
-229 ax2 . axvspan ( xmin = 0 , xmax = 0.33 , ymin = 0.66 , ymax = 1 ,
-230 alpha = alpha , color = all_colors [ 2 ])
-231
-232 # Column 2
-233 ax2 . axvspan ( xmin = 0.33 , xmax = 0.66 , ymin = 0 , ymax = 0.33 ,
-234 alpha = alpha , color = all_colors [ 3 ])
-235 ax2 . axvspan ( xmin = 0.33 , xmax = 0.66 , ymin = 0.33 , ymax = 0.66 ,
-236 alpha = alpha , color = all_colors [ 4 ])
-237 ax2 . axvspan ( xmin = 0.33 , xmax = 0.66 , ymin = 0.66 , ymax = 1 ,
-238 alpha = alpha , color = all_colors [ 5 ])
-239
-240 # Column 3
-241 ax2 . axvspan ( xmin = 0.66 , xmax = 1 , ymin = 0 , ymax = 0.33 ,
-242 alpha = alpha , color = all_colors [ 6 ])
-243 ax2 . axvspan ( xmin = 0.66 , xmax = 1 , ymin = 0.33 , ymax = 0.66 ,
-244 alpha = alpha , color = all_colors [ 7 ])
-245 ax2 . axvspan ( xmin = 0.66 , xmax = 1 , ymin = 0.66 , ymax = 1 ,
-246 alpha = alpha , color = all_colors [ 8 ])
-247
-248 # Step 3: annoate the legend
-249 # remove ticks from the big box
-250 ax2 . tick_params ( axis = 'both' , which = 'both' , length = 0 )
-251 ax2 . axis ( 'off' ) # turn off its axis
-252 ax2 . annotate ( "" , xy = ( 0 , 1 ), xytext = ( 0 , 0 ), arrowprops = dict (
-253 arrowstyle = "->" , lw = 1 , color = 'black' )) # draw arrow for x
-254 ax2 . annotate ( "" , xy = ( 1 , 0 ), xytext = ( 0 , 0 ), arrowprops = dict (
-255 arrowstyle = "->" , lw = 1 , color = 'black' )) # draw arrow for y
-256 ax2 . text ( s = x_label , x = 0.1 , y =- 0.25 , fontsize = 8 ) # annotate x axis
-257 ax2 . text ( s = y_label , x =- 0.25 , y = 0.1 , rotation = 90 ,
-258 fontsize = 8 ) # annotate y axis
-259 # plt.savefig('bivariate_choropleth.png', dpi=300)
-260
-261 if return_table :
-262 return data
-
-
-
-
-
-
-
-
-
-
- def
- nine_quadrants_plot (data , x_name , y_name , scale = True ):
-
- View Source
-
-
-
- 265 def nine_quadrants_plot ( data , x_name , y_name , scale = True ):
-266 _ , ax = plt . subplots ( figsize = ( 6 , 5 ))
-267
-268 if scale :
-269 scaler = MinMaxScaler ()
-270 # data[x_name] = scaler.fit_transform(data[x_name].values.reshape(-1, 1))
-271 # data[y_name] = scaler.fit_transform(data[y_name].values.reshape(-1, 1))
-272 # Scale data between 0 and 1
-273 data [ x_name ] = ( data [ x_name ] - data [ x_name ] . min ()) / \
-274 ( data [ x_name ] . max () - data [ x_name ] . min ())
-275 data [ y_name ] = ( data [ y_name ] - data [ y_name ] . min ()) / \
-276 ( data [ y_name ] . max () - data [ y_name ] . min ())
-277
-278 data . plot . scatter ( x_name , y_name , s = 20 , ax = ax , c = 'black' , zorder = 2 )
-279
-280 # Iterate over each row and annotate the points
-281 for idx , row in data . iterrows ():
-282 ax . annotate ( text = row [ 'NAME_1' ], xy = ( row [ x_name ], row [ y_name ]),
-283 ha = 'center' , fontsize = 10 , color = 'black' )
-284
-285 # Annotate with Spearman's rho
-286 # rho, p = spearmanr(data[x_name], data[y_name])
-287 # ax.text(0.05, 0.95, f'$\\rho$ = {round(rho, 2)}', transform=ax.transAxes,
-288 # verticalalignment='top', fontsize=12, bbox=dict(facecolor='white', edgecolor='black', alpha=1))
-289
-290 ax . axvline ( 0.33 , color = 'black' , alpha = .33 , lw = 1 )
-291 ax . axvline ( 0.66 , color = 'black' , alpha = .33 , lw = 1 )
-292 ax . axhline ( 0.33 , color = 'black' , alpha = .33 , lw = 1 )
-293 ax . axhline ( 0.66 , color = 'black' , alpha = .33 , lw = 1 )
-294
-295 alpha = 1
-296
-297 all_colors = { '1A' : '#dddddd' ,
-298 '1B' : '#dd7c8a' ,
-299 '1C' : '#cc0024' ,
-300 '2A' : '#7bb3d1' ,
-301 '2B' : '#8d6c8f' ,
-302 '2C' : '#8a274a' ,
-303 '3A' : '#016eae' ,
-304 '3B' : '#4a4779' ,
-305 '3C' : '#4b264d' }
-306
-307 # Column 1
-308 c = all_colors [ '1A' ]
-309 ax . axvspan ( xmin = 0 , xmax = 0.33 , ymin = 0 + 0.025 ,
-310 ymax = 0.345 , alpha = alpha , color = c )
-311
-312 c = all_colors [ '1B' ]
-313 ax . axvspan ( xmin = 0 , xmax = 0.33 , ymin = 0.33 + 0.015 ,
-314 ymax = 0.66 - 0.015 , alpha = alpha , color = c )
-315
-316 c = all_colors [ '1C' ]
-317 ax . axvspan ( xmin = 0 , xmax = 0.33 , ymin = 0.66 - 0.015 ,
-318 ymax = 1 - 0.05 , alpha = alpha , color = c )
-319
-320 # Column 2
-321 c = all_colors [ '2A' ]
-322 ax . axvspan ( xmin = 0.33 , xmax = 0.66 , ymin = 0 + 0.025 ,
-323 ymax = 0.345 , alpha = alpha , color = c )
-324
-325 c = all_colors [ '2B' ]
-326 ax . axvspan ( xmin = 0.33 , xmax = 0.66 , ymin = 0.345 ,
-327 ymax = 0.645 , alpha = alpha , color = c )
-328
-329 c = all_colors [ '2C' ]
-330 ax . axvspan ( xmin = 0.33 , xmax = 0.66 , ymin = 0.649 ,
-331 ymax = 1 - 0.05 , alpha = alpha , color = c )
-332
-333 # Column 3
-334 c = all_colors [ '3A' ]
-335 ax . axvspan ( xmin = 0.66 , xmax = 1 , ymin = 0.025 , ymax = 0.345 , alpha = alpha , color = c )
-336
-337 c = all_colors [ '3B' ]
-338 ax . axvspan ( xmin = 0.66 , xmax = 1 , ymin = 0.345 ,
-339 ymax = 0.645 , alpha = alpha , color = c )
-340
-341 c = all_colors [ '3C' ]
-342 ax . axvspan ( xmin = 0.66 , xmax = 1 , ymin = 0.649 ,
-343 ymax = 1 - 0.05 , alpha = alpha , color = c )
-344
-345 ax . set_xlim ( - .05 , 1.05 )
-346 ax . set_ylim ( - 0.05 , 1.05 )
-
-
-
-
-
-
-
-
-
-
- def
- get_colors (data ):
-
- View Source
-
-
-
- 355 def get_colors ( data ):
-356
-357 # colors = ['#e8e8e8', # 1A
-358 # '#b0d5df', # 1B
-359 # # '#64acbe', # 1C
-360 # '#e4acac', # 2A
-361 # '#ad9ea5', # 2B
-362 # '#627f8c', # 2C
-363 # '#c85a5a', # 3A
-364 # '#985356'] # , # 3B
-365 # # '#574249'] # 3C
-366
-367 all_colors = { '1A' : '#e8e8e8' ,
-368 '1B' : '#b0d5df' ,
-369 '1C' : '#64acbe' ,
-370 '2A' : '#e4acac' ,
-371 '2B' : '#ad9ea5' ,
-372 '2C' : '#627f8c' ,
-373 '3A' : '#c85a5a' ,
-374 '3B' : '#985356' ,
-375 '3C' : '#574249' }
-376
-377 all_colors = { '1A' : '#dddddd' ,
-378 '1B' : '#dd7c8a' ,
-379 '1C' : '#cc0024' ,
-380 '2A' : '#7bb3d1' ,
-381 '2B' : '#8d6c8f' ,
-382 '2C' : '#8a274a' ,
-383 '3A' : '#016eae' ,
-384 '3B' : '#4a4779' ,
-385 '3C' : '#4b264d' }
-386
-387 # Set of colors matching the elements of Bi_Class
-388 # We have to exclude those that did not come up in the data
-389 available_classes = data [ 'Bi_Class' ] . value_counts () . sort_index () . index
-390 available_colors = [ all_colors [ i ] for i in available_classes ]
-391 return list ( all_colors . values ()), available_colors
-
-
-
-
-
-
-
-
-
-
- def
- bin_data (data , x_name , y_name , scale , print_statistics = True ):
-
- View Source
-
-
-
- 394 def bin_data ( data , x_name , y_name , scale , print_statistics = True ):
-395 if scale :
-396 # Scale the data to be between 0 and 1
-397 # data[x_name] = (data[x_name] - data[x_name].min()) / \
-398 # (data[x_name].max() - data[x_name].min())
-399 # data[y_name] = (data[y_name] - data[y_name].min()) / \
-400 # (data[y_name].max() - data[y_name].min())
-401 # Scale the data with MinMaxScaler
-402 scaler = MinMaxScaler ()
-403 data [ x_name ] = scaler . fit_transform ( data [ x_name ] . values . reshape ( - 1 , 1 ))
-404 data [ y_name ] = scaler . fit_transform ( data [ y_name ] . values . reshape ( - 1 , 1 ))
-405
-406 # Define the bins
-407 bins = [ 0 , 0.33 , 0.66 , 1 ]
-408
-409 # Bin the first variable - x
-410 data [ 'Var1_Class' ] = pd . cut ( data [ x_name ], bins = bins , include_lowest = True )
-411 data [ 'Var1_Class' ] = data [ 'Var1_Class' ] . astype ( 'str' )
-412
-413 # Bin the second variable - y
-414 data [ 'Var2_Class' ] = pd . cut ( data [ y_name ], bins = bins , include_lowest = True )
-415 data [ 'Var2_Class' ] = data [ 'Var2_Class' ] . astype ( 'str' )
-416
-417 # Code created x bins to 1, 2, 3
-418 x_class_codes = np . arange ( 1 , len ( bins ))
-419 d = dict (
-420 zip ( data [ 'Var1_Class' ] . value_counts () . sort_index () . index , x_class_codes ))
-421 data [ 'Var1_Class' ] = data [ 'Var1_Class' ] . replace ( d )
-422
-423 # Code created y bins to A, B, C
-424 y_class_codes = [ 'A' , 'B' , 'C' ]
-425 d = dict (
-426 zip ( data [ 'Var2_Class' ] . value_counts () . sort_index () . index , y_class_codes ))
-427 data [ 'Var2_Class' ] = data [ 'Var2_Class' ] . replace ( d )
-428
-429 # Combine x and y codes to create Bi_Class
-430 data [ 'Bi_Class' ] = data [ 'Var1_Class' ] . astype ( 'str' ) + data [ 'Var2_Class' ]
-431
-432 if print_statistics :
-433 print ( 'Number of unique elements in Var1_Class =' ,
-434 len ( data [ 'Var1_Class' ] . unique ()))
-435 print ( 'Number of unique elements in Var2_Class =' ,
-436 len ( data [ 'Var2_Class' ] . unique ()))
-437 print ( 'Number of unique elements in Bi_Class =' ,
-438 len ( data [ 'Bi_Class' ] . unique ()))
-439 return data
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/src/data/write.html b/docs/src/data/write.html
deleted file mode 100644
index 95bcf59..0000000
--- a/docs/src/data/write.html
+++ /dev/null
@@ -1,992 +0,0 @@
-
-
-
-
-
-
- src.data.write API documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- View Source
-
- 1 # Specify which outcomes to store in each run of the simulation model
- 2
- 3 import pandas as pd
- 4 import numpy as np
- 5
- 6
- 7 def add_columns ( households : pd . DataFrame , affected_households : pd . DataFrame ) -> pd . DataFrame :
- 8 '''Add columns/outcomes of interest from `affected households` to the `households` dataframe.'''
- 9
- 10 # Outcomes of interest from affected households
- 11 outcomes_of_interest : list = [
- 12 'consumption_loss' ,
- 13 'consumption_loss_NPV' ,
- 14 'c_t' ,
- 15 'c_t_unaffected' ,
- 16 'recovery_rate' ,
- 17 'weeks_pov' ]
- 18
- 19 # Merge affected households onto households
- 20 columns = [ 'hhid' ] + outcomes_of_interest
- 21 households = pd . merge (
- 22 households , affected_households [ columns ], on = 'hhid' , how = 'left' )
- 23 return households
- 24
- 25
- 26 def get_outcomes ( households , event_damage , total_asset_stock , expected_loss_fraction , average_productivity , n_years ) -> dict :
- 27 '''Calculate outcomes of interest from the simulation model.
- 28
- 29 Args:
- 30 households (pd.DataFrame): Households data frame.
- 31 event_damage (float): Event damage.
- 32 total_asset_stock (float): Total asset stock.
- 33 expected_loss_fraction (float): Expected loss fraction.
- 34 average_productivity (float): Average productivity.
- 35 n_years (float): Number of years to consider for calculations (same as for optimization algorithm).
- 36
- 37 Returns:
- 38 dict: Outcomes of interest.
- 39 '''
- 40 # Save some outcomes for verification
- 41 total_population = households [ 'popwgt' ] . sum ()
- 42 total_asset_in_survey = households [ 'total_asset_in_survey' ] . iloc [ 0 ]
- 43
- 44 # Actual outcomes of interest
- 45 affected_households = households [ households [ 'is_affected' ] == True ]
- 46 total_asset_loss = affected_households [[
- 47 'keff' , 'v' , 'popwgt' ]] . prod ( axis = 1 ) . sum ()
- 48 total_consumption_loss = affected_households [[
- 49 'consumption_loss_NPV' , 'popwgt' ]] . prod ( axis = 1 ) . sum ()
- 50 n_affected_people = affected_households [ 'popwgt' ] . sum ()
- 51 annual_average_consumption = (
- 52 households [ 'aeexp' ] * households [ 'popwgt' ]) . sum () / households [ 'popwgt' ] . sum ()
- 53 recovery_rate = households [ 'recovery_rate' ] . mean ()
- 54
- 55 # * Poverty line is different across replications
- 56 poverty_line_adjusted = households [ 'poverty_line_adjusted' ] . values [ 0 ]
- 57
- 58 # Get PML, its the same across replications and stored in households
- 59 pml = households [ 'pml' ] . iloc [ 0 ]
- 60
- 61 # Run statistics
- 62 no_affected_households = 0
- 63 zero_consumption_loss = 0
- 64
- 65 # * Some runs give no affected households and we will skip these
- 66 if len ( affected_households ) == 0 :
- 67 no_affected_households += 1
- 68 pass
- 69
- 70 # * Sometimes households are affected but they have no consumption loss
- 71 if affected_households [ 'consumption_loss_NPV' ] . sum () == 0 :
- 72 zero_consumption_loss += 1
- 73 pass
- 74
- 75 # Calculate outcomes of interest
- 76 n_poor_initial , n_new_poor , n_poor_affected , poor_initial , new_poor = find_poor (
- 77 households , poverty_line_adjusted , n_years )
- 78
- 79 years_in_poverty = get_people_by_years_in_poverty ( new_poor )
- 80
- 81 initial_poverty_gap , new_poverty_gap = calculate_poverty_gap (
- 82 poor_initial , new_poor , poverty_line_adjusted , n_years )
- 83
- 84 annual_average_consumption_loss , annual_average_consumption_loss_pct = calculate_average_annual_consumption_loss (
- 85 affected_households , n_years )
- 86
- 87 r = calculate_resilience (
- 88 affected_households , pml )
- 89
- 90 return {
- 91 'total_population' : total_population ,
- 92 'total_asset_loss' : total_asset_loss ,
- 93 'total_consumption_loss' : total_consumption_loss ,
- 94 'event_damage' : event_damage ,
- 95 'total_asset_stock' : total_asset_stock ,
- 96 'average_productivity' : average_productivity ,
- 97 'total_asset_in_survey' : total_asset_in_survey ,
- 98 'expected_loss_fraction' : expected_loss_fraction ,
- 99 'n_affected_people' : n_affected_people ,
-100 'annual_average_consumption' : annual_average_consumption ,
-101 'poverty_line_adjusted' : poverty_line_adjusted ,
-102 'pml' : pml ,
-103 'n_poor_initial' : n_poor_initial ,
-104 'n_poor_affected' : n_poor_affected ,
-105 'n_new_poor' : n_new_poor ,
-106 'initial_poverty_gap' : initial_poverty_gap ,
-107 'new_poverty_gap' : new_poverty_gap ,
-108 'annual_average_consumption_loss' : annual_average_consumption_loss ,
-109 'annual_average_consumption_loss_pct' : annual_average_consumption_loss_pct ,
-110 'r' : r ,
-111 'recovery_rate' : recovery_rate ,
-112 'years_in_poverty' : years_in_poverty
-113 # 'n_resilience_more_than_1' : n_resilience_more_than_1
-114 }
-115
-116
-117 def find_poor ( households : pd . DataFrame , poverty_line : float , n_years : int ) -> tuple :
-118 '''Get the poor at the beginning of the simulation and the poor at the end of the simulation
-119
-120 Args:
-121 households (pd.DataFrame): Household dataframe
-122 poverty_line (float): Poverty line
-123
-124 Returns:
-125 tuple: Number of poor at the beginning of the simulation, number of new poor at the end of the simulation, and the new poor dataframe
-126 '''
-127 # First, find the poor at the beginning of the simulation
-128 poor_initial = households [ households [ 'is_poor' ] == True ]
-129 n_poor_initial = round ( poor_initial [ 'popwgt' ] . sum ())
-130 n_poor_affected = round (
-131 poor_initial [ poor_initial [ 'is_affected' ] == True ][ 'popwgt' ] . sum ())
-132
-133 # Second, find the new poor at the end of the simulation (`n_years`)
-134 not_poor = households [ households [ 'is_poor' ] == False ]
-135 not_poor_affected = not_poor [ not_poor [ 'is_affected' ] == True ]
-136 x = not_poor_affected [ 'aeexp' ] - \
-137 not_poor_affected [ 'consumption_loss_NPV' ] / n_years
-138 new_poor = not_poor_affected . loc [ x < poverty_line , :]
-139 n_new_poor = round ( new_poor [ 'popwgt' ] . sum ())
-140
-141 return n_poor_initial , n_new_poor , n_poor_affected , poor_initial , new_poor
-142
-143
-144 def get_people_by_years_in_poverty ( new_poor : pd . DataFrame ) -> dict :
-145 '''Get the number of people in poverty for each year in poverty.
-146
-147 Args:
-148 new_poor (pd.DataFrame): New poor dataframe
-149
-150 Returns:
-151 dict: Number of people in poverty for each year in poverty
-152 '''
-153 new_poor = new_poor . assign (
-154 years_in_poverty = new_poor [ 'weeks_pov' ] // 52 )
-155 d = {}
-156 # !: This cannot be higher > n_years
-157 longest_years_in_poverty = 10
-158 for i in range ( longest_years_in_poverty ):
-159 d [ i ] = round ( new_poor [ new_poor [ 'years_in_poverty' ] == i ]
-160 [ 'popwgt' ] . sum ())
-161 d [ longest_years_in_poverty ] = round (
-162 new_poor [ new_poor [ 'years_in_poverty' ] >= longest_years_in_poverty ][ 'popwgt' ] . sum ())
-163
-164 return d
-165
-166
-167 def calculate_poverty_gap ( poor_initial : pd . DataFrame , new_poor : pd . DataFrame , poverty_line : float , n_years : int ) -> tuple :
-168 '''Calculate the poverty gap at the beginning and at the end of the simulation.
-169
-170 Args:
-171 poor_initial (pd.DataFrame): Poor at the beginning of the simulation
-172 new_poor (pd.DataFrame): New poor at the end of the simulation
-173 poverty_line (float): Poverty line
-174 n_years (int): Number of years of the optimization algorithm
-175
-176 Returns:
-177 tuple: Poverty gap at the beginning and at the end of the simulation
-178
-179 Raises:
-180 Exception: If the index is duplicated
-181 Exception: If the poverty gap is greater than 1
-182 '''
-183 # First, get the average expenditure of the poor at the beginning of the simulation
-184 average_expenditure_poor_initial = (
-185 poor_initial [ 'aeexp' ] * poor_initial [ 'popwgt' ]) . sum () / poor_initial [ 'popwgt' ] . sum ()
-186 initial_poverty_gap = (
-187 poverty_line - average_expenditure_poor_initial ) / poverty_line
-188
-189 new_poor [ 'aeexp' ] = new_poor [ 'aeexp' ] - \
-190 new_poor [ 'consumption_loss_NPV' ] / n_years
-191
-192 all_poor = pd . concat ([ poor_initial , new_poor ])
-193
-194 # Now, get the average expenditure of the poor at the end of the simulation
-195 average_expenditure_poor_new = (
-196 all_poor [ 'aeexp' ] * all_poor [ 'popwgt' ]) . sum () / all_poor [ 'popwgt' ] . sum ()
-197 new_poverty_gap = (
-198 poverty_line - average_expenditure_poor_new ) / poverty_line
-199
-200 # Poverty gap cannot be greater than 1
-201 if new_poverty_gap > 1 or initial_poverty_gap > 1 :
-202 raise Exception ( 'Poverty gap is greater than 1' )
-203
-204 return initial_poverty_gap , new_poverty_gap
-205
-206
-207 def calculate_average_annual_consumption_loss ( affected_households : pd . DataFrame , n_years : int ) -> tuple :
-208 '''Get the average annual consumption loss and the average annual consumption loss as a percentage of average annual consumption.
-209
-210 Args:
-211 affected_households (pd.DataFrame): Affected households dataframe
-212 n_years (int): Number of years of the optimization algorithm
-213
-214 Returns:
-215 tuple: Average annual consumption loss and average annual consumption loss as a percentage of average annual consumption
-216
-217 Raises:
-218 Exception: If the average annual consumption loss is greater than 1
-219 '''
-220
-221 if len ( affected_households ) == 0 :
-222 return np . nan , np . nan
-223
-224 # Annual consumption loss
-225 annual_consumption_loss = (
-226 affected_households [ 'consumption_loss_NPV' ] . div ( n_years ) . multiply ( affected_households [ 'popwgt' ])) . sum ()
-227
-228 # Weighted average
-229 annual_average_consumption_loss = annual_consumption_loss / \
-230 affected_households [ 'popwgt' ] . sum ()
-231
-232 # Annual average consumption
-233 annual_average_consumption = (
-234 affected_households [ 'aeexp' ] * affected_households [ 'popwgt' ]) . sum () / \
-235 affected_households [ 'popwgt' ] . sum ()
-236
-237 # Annual average consumption loss as a percentage of average annual consumption
-238 annual_average_consumption_loss_pct = annual_average_consumption_loss / \
-239 annual_average_consumption
-240
-241 if annual_average_consumption_loss_pct > 1 :
-242 raise Exception (
-243 'Annual average consumption loss is greater than 1' )
-244
-245 return annual_average_consumption_loss , annual_average_consumption_loss_pct
-246
-247
-248 def calculate_resilience ( affected_households : pd . DataFrame , pml : float ,
-249 # n_resilience_more_than_1: int
-250 ) -> tuple :
-251 '''Calculate the resilience of the affected households.
-252
-253 Args:
-254 affected_households (pd.DataFrame): Affected households dataframe
-255 pml (float): Probable maximum loss
-256
-257 Returns:
-258 tuple: Resilience and number of times resilience is greater than 1
-259
-260 Raises:
-261 Exception: If the total consumption loss is 0
-262 '''
-263 total_consumption_loss = (
-264 affected_households [ 'consumption_loss_NPV' ] * affected_households [ 'popwgt' ]) . sum ()
-265
-266 if total_consumption_loss == 0 :
-267 # raise Exception('Total consumption loss is 0')
-268 r = np . nan
-269 else :
-270 r = pml / total_consumption_loss
-271
-272 # !: Sometimes resilience is greater than 1
-273 # We will set it to 1 then
-274 # if r > 5:
-275 # r = 1
-276 # # raise Exception('Resilience is greater than 1')
-277 # # n_resilience_more_than_1 += 1
-278 # # continue
-279 return r
-
-
-
-
-
-
-
-
- def
- add_columns ( households : pandas . core . frame . DataFrame , affected_households : pandas . core . frame . DataFrame ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 8 def add_columns ( households : pd . DataFrame , affected_households : pd . DataFrame ) -> pd . DataFrame :
- 9 '''Add columns/outcomes of interest from `affected households` to the `households` dataframe.'''
-10
-11 # Outcomes of interest from affected households
-12 outcomes_of_interest : list = [
-13 'consumption_loss' ,
-14 'consumption_loss_NPV' ,
-15 'c_t' ,
-16 'c_t_unaffected' ,
-17 'recovery_rate' ,
-18 'weeks_pov' ]
-19
-20 # Merge affected households onto households
-21 columns = [ 'hhid' ] + outcomes_of_interest
-22 households = pd . merge (
-23 households , affected_households [ columns ], on = 'hhid' , how = 'left' )
-24 return households
-
-
-
- Add columns/outcomes of interest from affected households
to the households
dataframe.
-
-
-
-
-
-
-
-
- def
- get_outcomes ( households , event_damage , total_asset_stock , expected_loss_fraction , average_productivity , n_years ) -> dict :
-
- View Source
-
-
-
- 27 def get_outcomes ( households , event_damage , total_asset_stock , expected_loss_fraction , average_productivity , n_years ) -> dict :
- 28 '''Calculate outcomes of interest from the simulation model.
- 29
- 30 Args:
- 31 households (pd.DataFrame): Households data frame.
- 32 event_damage (float): Event damage.
- 33 total_asset_stock (float): Total asset stock.
- 34 expected_loss_fraction (float): Expected loss fraction.
- 35 average_productivity (float): Average productivity.
- 36 n_years (float): Number of years to consider for calculations (same as for optimization algorithm).
- 37
- 38 Returns:
- 39 dict: Outcomes of interest.
- 40 '''
- 41 # Save some outcomes for verification
- 42 total_population = households [ 'popwgt' ] . sum ()
- 43 total_asset_in_survey = households [ 'total_asset_in_survey' ] . iloc [ 0 ]
- 44
- 45 # Actual outcomes of interest
- 46 affected_households = households [ households [ 'is_affected' ] == True ]
- 47 total_asset_loss = affected_households [[
- 48 'keff' , 'v' , 'popwgt' ]] . prod ( axis = 1 ) . sum ()
- 49 total_consumption_loss = affected_households [[
- 50 'consumption_loss_NPV' , 'popwgt' ]] . prod ( axis = 1 ) . sum ()
- 51 n_affected_people = affected_households [ 'popwgt' ] . sum ()
- 52 annual_average_consumption = (
- 53 households [ 'aeexp' ] * households [ 'popwgt' ]) . sum () / households [ 'popwgt' ] . sum ()
- 54 recovery_rate = households [ 'recovery_rate' ] . mean ()
- 55
- 56 # * Poverty line is different across replications
- 57 poverty_line_adjusted = households [ 'poverty_line_adjusted' ] . values [ 0 ]
- 58
- 59 # Get PML, its the same across replications and stored in households
- 60 pml = households [ 'pml' ] . iloc [ 0 ]
- 61
- 62 # Run statistics
- 63 no_affected_households = 0
- 64 zero_consumption_loss = 0
- 65
- 66 # * Some runs give no affected households and we will skip these
- 67 if len ( affected_households ) == 0 :
- 68 no_affected_households += 1
- 69 pass
- 70
- 71 # * Sometimes households are affected but they have no consumption loss
- 72 if affected_households [ 'consumption_loss_NPV' ] . sum () == 0 :
- 73 zero_consumption_loss += 1
- 74 pass
- 75
- 76 # Calculate outcomes of interest
- 77 n_poor_initial , n_new_poor , n_poor_affected , poor_initial , new_poor = find_poor (
- 78 households , poverty_line_adjusted , n_years )
- 79
- 80 years_in_poverty = get_people_by_years_in_poverty ( new_poor )
- 81
- 82 initial_poverty_gap , new_poverty_gap = calculate_poverty_gap (
- 83 poor_initial , new_poor , poverty_line_adjusted , n_years )
- 84
- 85 annual_average_consumption_loss , annual_average_consumption_loss_pct = calculate_average_annual_consumption_loss (
- 86 affected_households , n_years )
- 87
- 88 r = calculate_resilience (
- 89 affected_households , pml )
- 90
- 91 return {
- 92 'total_population' : total_population ,
- 93 'total_asset_loss' : total_asset_loss ,
- 94 'total_consumption_loss' : total_consumption_loss ,
- 95 'event_damage' : event_damage ,
- 96 'total_asset_stock' : total_asset_stock ,
- 97 'average_productivity' : average_productivity ,
- 98 'total_asset_in_survey' : total_asset_in_survey ,
- 99 'expected_loss_fraction' : expected_loss_fraction ,
-100 'n_affected_people' : n_affected_people ,
-101 'annual_average_consumption' : annual_average_consumption ,
-102 'poverty_line_adjusted' : poverty_line_adjusted ,
-103 'pml' : pml ,
-104 'n_poor_initial' : n_poor_initial ,
-105 'n_poor_affected' : n_poor_affected ,
-106 'n_new_poor' : n_new_poor ,
-107 'initial_poverty_gap' : initial_poverty_gap ,
-108 'new_poverty_gap' : new_poverty_gap ,
-109 'annual_average_consumption_loss' : annual_average_consumption_loss ,
-110 'annual_average_consumption_loss_pct' : annual_average_consumption_loss_pct ,
-111 'r' : r ,
-112 'recovery_rate' : recovery_rate ,
-113 'years_in_poverty' : years_in_poverty
-114 # 'n_resilience_more_than_1' : n_resilience_more_than_1
-115 }
-
-
-
- Calculate outcomes of interest from the simulation model.
-
-
Args:
- households (pd.DataFrame): Households data frame.
- event_damage (float): Event damage.
- total_asset_stock (float): Total asset stock.
- expected_loss_fraction (float): Expected loss fraction.
- average_productivity (float): Average productivity.
- n_years (float): Number of years to consider for calculations (same as for optimization algorithm).
-
-
Returns:
- dict: Outcomes of interest.
-
-
-
-
-
-
-
-
- def
- find_poor ( households : pandas . core . frame . DataFrame , poverty_line : float , n_years : int ) -> tuple :
-
- View Source
-
-
-
- 118 def find_poor ( households : pd . DataFrame , poverty_line : float , n_years : int ) -> tuple :
-119 '''Get the poor at the beginning of the simulation and the poor at the end of the simulation
-120
-121 Args:
-122 households (pd.DataFrame): Household dataframe
-123 poverty_line (float): Poverty line
-124
-125 Returns:
-126 tuple: Number of poor at the beginning of the simulation, number of new poor at the end of the simulation, and the new poor dataframe
-127 '''
-128 # First, find the poor at the beginning of the simulation
-129 poor_initial = households [ households [ 'is_poor' ] == True ]
-130 n_poor_initial = round ( poor_initial [ 'popwgt' ] . sum ())
-131 n_poor_affected = round (
-132 poor_initial [ poor_initial [ 'is_affected' ] == True ][ 'popwgt' ] . sum ())
-133
-134 # Second, find the new poor at the end of the simulation (`n_years`)
-135 not_poor = households [ households [ 'is_poor' ] == False ]
-136 not_poor_affected = not_poor [ not_poor [ 'is_affected' ] == True ]
-137 x = not_poor_affected [ 'aeexp' ] - \
-138 not_poor_affected [ 'consumption_loss_NPV' ] / n_years
-139 new_poor = not_poor_affected . loc [ x < poverty_line , :]
-140 n_new_poor = round ( new_poor [ 'popwgt' ] . sum ())
-141
-142 return n_poor_initial , n_new_poor , n_poor_affected , poor_initial , new_poor
-
-
-
- Get the poor at the beginning of the simulation and the poor at the end of the simulation
-
-
Args:
- households (pd.DataFrame): Household dataframe
- poverty_line (float): Poverty line
-
-
Returns:
- tuple: Number of poor at the beginning of the simulation, number of new poor at the end of the simulation, and the new poor dataframe
-
-
-
-
-
-
-
-
- def
- get_people_by_years_in_poverty (new_poor : pandas . core . frame . DataFrame ) -> dict :
-
- View Source
-
-
-
- 145 def get_people_by_years_in_poverty ( new_poor : pd . DataFrame ) -> dict :
-146 '''Get the number of people in poverty for each year in poverty.
-147
-148 Args:
-149 new_poor (pd.DataFrame): New poor dataframe
-150
-151 Returns:
-152 dict: Number of people in poverty for each year in poverty
-153 '''
-154 new_poor = new_poor . assign (
-155 years_in_poverty = new_poor [ 'weeks_pov' ] // 52 )
-156 d = {}
-157 # !: This cannot be higher > n_years
-158 longest_years_in_poverty = 10
-159 for i in range ( longest_years_in_poverty ):
-160 d [ i ] = round ( new_poor [ new_poor [ 'years_in_poverty' ] == i ]
-161 [ 'popwgt' ] . sum ())
-162 d [ longest_years_in_poverty ] = round (
-163 new_poor [ new_poor [ 'years_in_poverty' ] >= longest_years_in_poverty ][ 'popwgt' ] . sum ())
-164
-165 return d
-
-
-
- Get the number of people in poverty for each year in poverty.
-
-
Args:
- new_poor (pd.DataFrame): New poor dataframe
-
-
Returns:
- dict: Number of people in poverty for each year in poverty
-
-
-
-
-
-
-
-
- def
- calculate_poverty_gap ( poor_initial : pandas . core . frame . DataFrame , new_poor : pandas . core . frame . DataFrame , poverty_line : float , n_years : int ) -> tuple :
-
- View Source
-
-
-
- 168 def calculate_poverty_gap ( poor_initial : pd . DataFrame , new_poor : pd . DataFrame , poverty_line : float , n_years : int ) -> tuple :
-169 '''Calculate the poverty gap at the beginning and at the end of the simulation.
-170
-171 Args:
-172 poor_initial (pd.DataFrame): Poor at the beginning of the simulation
-173 new_poor (pd.DataFrame): New poor at the end of the simulation
-174 poverty_line (float): Poverty line
-175 n_years (int): Number of years of the optimization algorithm
-176
-177 Returns:
-178 tuple: Poverty gap at the beginning and at the end of the simulation
-179
-180 Raises:
-181 Exception: If the index is duplicated
-182 Exception: If the poverty gap is greater than 1
-183 '''
-184 # First, get the average expenditure of the poor at the beginning of the simulation
-185 average_expenditure_poor_initial = (
-186 poor_initial [ 'aeexp' ] * poor_initial [ 'popwgt' ]) . sum () / poor_initial [ 'popwgt' ] . sum ()
-187 initial_poverty_gap = (
-188 poverty_line - average_expenditure_poor_initial ) / poverty_line
-189
-190 new_poor [ 'aeexp' ] = new_poor [ 'aeexp' ] - \
-191 new_poor [ 'consumption_loss_NPV' ] / n_years
-192
-193 all_poor = pd . concat ([ poor_initial , new_poor ])
-194
-195 # Now, get the average expenditure of the poor at the end of the simulation
-196 average_expenditure_poor_new = (
-197 all_poor [ 'aeexp' ] * all_poor [ 'popwgt' ]) . sum () / all_poor [ 'popwgt' ] . sum ()
-198 new_poverty_gap = (
-199 poverty_line - average_expenditure_poor_new ) / poverty_line
-200
-201 # Poverty gap cannot be greater than 1
-202 if new_poverty_gap > 1 or initial_poverty_gap > 1 :
-203 raise Exception ( 'Poverty gap is greater than 1' )
-204
-205 return initial_poverty_gap , new_poverty_gap
-
-
-
- Calculate the poverty gap at the beginning and at the end of the simulation.
-
-
Args:
- poor_initial (pd.DataFrame): Poor at the beginning of the simulation
- new_poor (pd.DataFrame): New poor at the end of the simulation
- poverty_line (float): Poverty line
- n_years (int): Number of years of the optimization algorithm
-
-
Returns:
- tuple: Poverty gap at the beginning and at the end of the simulation
-
-
Raises:
- Exception: If the index is duplicated
- Exception: If the poverty gap is greater than 1
-
-
-
-
-
-
-
-
- def
- calculate_average_annual_consumption_loss (affected_households : pandas . core . frame . DataFrame , n_years : int ) -> tuple :
-
- View Source
-
-
-
- 208 def calculate_average_annual_consumption_loss ( affected_households : pd . DataFrame , n_years : int ) -> tuple :
-209 '''Get the average annual consumption loss and the average annual consumption loss as a percentage of average annual consumption.
-210
-211 Args:
-212 affected_households (pd.DataFrame): Affected households dataframe
-213 n_years (int): Number of years of the optimization algorithm
-214
-215 Returns:
-216 tuple: Average annual consumption loss and average annual consumption loss as a percentage of average annual consumption
-217
-218 Raises:
-219 Exception: If the average annual consumption loss is greater than 1
-220 '''
-221
-222 if len ( affected_households ) == 0 :
-223 return np . nan , np . nan
-224
-225 # Annual consumption loss
-226 annual_consumption_loss = (
-227 affected_households [ 'consumption_loss_NPV' ] . div ( n_years ) . multiply ( affected_households [ 'popwgt' ])) . sum ()
-228
-229 # Weighted average
-230 annual_average_consumption_loss = annual_consumption_loss / \
-231 affected_households [ 'popwgt' ] . sum ()
-232
-233 # Annual average consumption
-234 annual_average_consumption = (
-235 affected_households [ 'aeexp' ] * affected_households [ 'popwgt' ]) . sum () / \
-236 affected_households [ 'popwgt' ] . sum ()
-237
-238 # Annual average consumption loss as a percentage of average annual consumption
-239 annual_average_consumption_loss_pct = annual_average_consumption_loss / \
-240 annual_average_consumption
-241
-242 if annual_average_consumption_loss_pct > 1 :
-243 raise Exception (
-244 'Annual average consumption loss is greater than 1' )
-245
-246 return annual_average_consumption_loss , annual_average_consumption_loss_pct
-
-
-
- Get the average annual consumption loss and the average annual consumption loss as a percentage of average annual consumption.
-
-
Args:
- affected_households (pd.DataFrame): Affected households dataframe
- n_years (int): Number of years of the optimization algorithm
-
-
Returns:
- tuple: Average annual consumption loss and average annual consumption loss as a percentage of average annual consumption
-
-
Raises:
- Exception: If the average annual consumption loss is greater than 1
-
-
-
-
-
-
-
-
- def
- calculate_resilience (affected_households : pandas . core . frame . DataFrame , pml : float ) -> tuple :
-
- View Source
-
-
-
- 249 def calculate_resilience ( affected_households : pd . DataFrame , pml : float ,
-250 # n_resilience_more_than_1: int
-251 ) -> tuple :
-252 '''Calculate the resilience of the affected households.
-253
-254 Args:
-255 affected_households (pd.DataFrame): Affected households dataframe
-256 pml (float): Probable maximum loss
-257
-258 Returns:
-259 tuple: Resilience and number of times resilience is greater than 1
-260
-261 Raises:
-262 Exception: If the total consumption loss is 0
-263 '''
-264 total_consumption_loss = (
-265 affected_households [ 'consumption_loss_NPV' ] * affected_households [ 'popwgt' ]) . sum ()
-266
-267 if total_consumption_loss == 0 :
-268 # raise Exception('Total consumption loss is 0')
-269 r = np . nan
-270 else :
-271 r = pml / total_consumption_loss
-272
-273 # !: Sometimes resilience is greater than 1
-274 # We will set it to 1 then
-275 # if r > 5:
-276 # r = 1
-277 # # raise Exception('Resilience is greater than 1')
-278 # # n_resilience_more_than_1 += 1
-279 # # continue
-280 return r
-
-
-
- Calculate the resilience of the affected households.
-
-
Args:
- affected_households (pd.DataFrame): Affected households dataframe
- pml (float): Probable maximum loss
-
-
Returns:
- tuple: Resilience and number of times resilience is greater than 1
-
-
Raises:
- Exception: If the total consumption loss is 0
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/src/model.html b/docs/src/model.html
deleted file mode 100644
index 17d685e..0000000
--- a/docs/src/model.html
+++ /dev/null
@@ -1,580 +0,0 @@
-
-
-
-
-
-
- src.model API documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-src .model
-
-
-
-
- View Source
-
- 1 # The model function pipeline, which is called by the ema_workbench in `__main__.py`.
- 2
- 3 import pandas as pd
- 4 import numpy as np
- 5 import random
- 6 import matplotlib.pyplot as plt
- 7 from src.data.read import *
- 8 from src.data.write import *
- 9 from src.modules.optimize import *
- 10 from src.modules.households import *
- 11
- 12
- 13 def initialize_model ( country : str , min_households : int ) -> tuple :
- 14 '''Initialize the model by reading household survey and asset damage files.
- 15
- 16 Args:
- 17 country (str): Country name.
- 18 min_households (int): Minimum number of households that we need to have in a sample to be representative.
- 19
- 20 Returns:
- 21 tuple: Household survey and asset damage files.
- 22 '''
- 23
- 24 # Read household survey and asset damage files
- 25 household_survey = read_household_survey ( country )
- 26 all_damage = read_asset_damage ( country )
- 27
- 28 # Duplicate households to have at least `min_households` households
- 29 household_survey = duplicate_households ( household_survey , min_households )
- 30
- 31 return household_survey , all_damage
- 32
- 33
- 34 def run_model ( ** kwargs ):
- 35 '''Run the model.'''
- 36 # ------------------------- Read the model parameters ------------------------ #
- 37 country = kwargs [ 'country' ]
- 38 scale = kwargs [ 'scale' ]
- 39 districts = kwargs [ 'districts' ]
- 40 min_households = kwargs [ 'min_households' ]
- 41
- 42 # Read household survey and asset damage files
- 43 household_survey , all_damage = initialize_model (
- 44 country , min_households )
- 45
- 46 # Case study constants
- 47 return_period = kwargs [ 'return_period' ]
- 48 poverty_line = kwargs [ 'poverty_line' ]
- 49 indigence_line = kwargs [ 'indigence_line' ]
- 50 saving_rate = kwargs [ 'saving_rate' ]
- 51 is_vulnerability_random = kwargs [ 'is_vulnerability_random' ]
- 52 n_years = kwargs [ 'n_years' ] # number of years in optimization algorithm
- 53
- 54 # Model constants
- 55 estimate_savings_params = kwargs [ 'estimate_savings_params' ]
- 56 set_vulnerability_params = kwargs [ 'set_vulnerability_params' ]
- 57 calculate_exposure_params = kwargs [ 'calculate_exposure_params' ]
- 58 determine_affected_params = kwargs [ 'determine_affected_params' ]
- 59
- 60 # Uncertainties
- 61 poverty_bias = kwargs [ 'poverty_bias' ]
- 62 consumption_utility = kwargs [ 'consumption_utility' ]
- 63 discount_rate = kwargs [ 'discount_rate' ]
- 64 optimization_timestep = kwargs [ 'optimization_timestep' ]
- 65 income_and_expenditure_growth = kwargs [ 'income_and_expenditure_growth' ]
- 66
- 67 # Policy levers
- 68 try :
- 69 my_policy = kwargs [ 'my_policy' ]
- 70 except :
- 71 # If a policy is not provided, use the default policy
- 72 my_policy = 'all+0'
- 73
- 74 add_income_loss = kwargs [ 'add_income_loss' ]
- 75
- 76 # Outcomes
- 77 # Store outcomes in a dictionary, where the key is a district and value is a dictionary of outcomes
- 78 outcomes = {}
- 79
- 80 # Print statistics for debugging
- 81 print_statistics = kwargs [ 'print_statistics' ]
- 82
- 83 # Fix random seed for reproducibility
- 84 random_seed = kwargs [ 'random_seed' ]
- 85 random . seed ( random_seed )
- 86 np . random . seed ( random_seed )
- 87
- 88 # PIPELINE:
- 89 # 1. Load all damage
- 90 # 2. Load household survey
- 91 # 3. Select district
- 92 # 4. Get event damage, total asset stock, expected loss fraction
- 93 # 5. Calculate average productivity
- 94 # 6. Adjust assets and expenditure
- 95 # 7. Calculate PML
- 96 # 8. Estimate savings
- 97 # 9. Set vulnerability
- 98 # 10. Calculate exposure
- 99 # 11. Determine affected
-100 # 12. Apply individual policy
-101 # 13. Run optimization
-102 # 14. Integrate wellbeing
-103 # 15. Prepare outcomes
-104 # 16. Get outcomes
-105
-106 # ---------------------- Run the model for each district --------------------- #
-107
-108 for district in districts :
-109 # Read household survey and asset damage files for a specific district
-110 event_damage , total_asset_stock , expected_loss_fraction = get_asset_damage (
-111 all_damage , scale , district , return_period , print_statistics )
-112
-113 households = select_district ( household_survey , district )
-114
-115 average_productivity = calculate_average_productivity (
-116 households , print_statistics )
-117
-118 # Model the impact of a disaster on households
-119 households = ( adjust_assets_and_expenditure ( households , total_asset_stock , poverty_line , indigence_line , print_statistics )
-120 . pipe ( calculate_pml , expected_loss_fraction , print_statistics )
-121 . pipe ( estimate_savings , saving_rate , estimate_savings_params )
-122 . pipe ( set_vulnerability , is_vulnerability_random , set_vulnerability_params )
-123 . pipe ( calculate_exposure , poverty_bias , calculate_exposure_params , print_statistics )
-124 . pipe ( determine_affected , determine_affected_params ))
-125
-126 # households['aesav'].hist()
-127 # plt.show()
-128
-129 # Apply a policy
-130 households , affected_households = apply_individual_policy (
-131 households , my_policy )
-132
-133 # Calculate the impact and recovery
-134 # cash_transfer = {52: 1000, 208: 5000}
-135 cash_transfer = {}
-136 affected_households = ( run_optimization ( affected_households , consumption_utility , discount_rate , average_productivity , optimization_timestep , n_years )
-137 . pipe ( integrate_wellbeing , consumption_utility , discount_rate , income_and_expenditure_growth , average_productivity , poverty_line , n_years , add_income_loss , cash_transfer ))
-138
-139 # Add columns of affected households to the original households dataframe
-140 households = add_columns ( households , affected_households )
-141 # Get outcomes
-142 array_outcomes = np . array ( list ( get_outcomes (
-143 households , event_damage , total_asset_stock , expected_loss_fraction , average_productivity , n_years ) . values ()))
-144
-145 # * To check whether we have different households affected in different runs
-146 # if district == 'Castries':
-147 # affected_households.to_csv(f'affected_households_{random_seed}.csv')
-148
-149 outcomes [ district ] = array_outcomes
-150
-151 return outcomes
-
-
-
-
-
-
-
-
- def
- initialize_model (country : str , min_households : int ) -> tuple :
-
- View Source
-
-
-
- 14 def initialize_model ( country : str , min_households : int ) -> tuple :
-15 '''Initialize the model by reading household survey and asset damage files.
-16
-17 Args:
-18 country (str): Country name.
-19 min_households (int): Minimum number of households that we need to have in a sample to be representative.
-20
-21 Returns:
-22 tuple: Household survey and asset damage files.
-23 '''
-24
-25 # Read household survey and asset damage files
-26 household_survey = read_household_survey ( country )
-27 all_damage = read_asset_damage ( country )
-28
-29 # Duplicate households to have at least `min_households` households
-30 household_survey = duplicate_households ( household_survey , min_households )
-31
-32 return household_survey , all_damage
-
-
-
- Initialize the model by reading household survey and asset damage files.
-
-
Args:
- country (str): Country name.
- min_households (int): Minimum number of households that we need to have in a sample to be representative.
-
-
Returns:
- tuple: Household survey and asset damage files.
-
-
-
-
-
-
-
-
- def
- run_model (** kwargs ):
-
- View Source
-
-
-
- 35 def run_model ( ** kwargs ):
- 36 '''Run the model.'''
- 37 # ------------------------- Read the model parameters ------------------------ #
- 38 country = kwargs [ 'country' ]
- 39 scale = kwargs [ 'scale' ]
- 40 districts = kwargs [ 'districts' ]
- 41 min_households = kwargs [ 'min_households' ]
- 42
- 43 # Read household survey and asset damage files
- 44 household_survey , all_damage = initialize_model (
- 45 country , min_households )
- 46
- 47 # Case study constants
- 48 return_period = kwargs [ 'return_period' ]
- 49 poverty_line = kwargs [ 'poverty_line' ]
- 50 indigence_line = kwargs [ 'indigence_line' ]
- 51 saving_rate = kwargs [ 'saving_rate' ]
- 52 is_vulnerability_random = kwargs [ 'is_vulnerability_random' ]
- 53 n_years = kwargs [ 'n_years' ] # number of years in optimization algorithm
- 54
- 55 # Model constants
- 56 estimate_savings_params = kwargs [ 'estimate_savings_params' ]
- 57 set_vulnerability_params = kwargs [ 'set_vulnerability_params' ]
- 58 calculate_exposure_params = kwargs [ 'calculate_exposure_params' ]
- 59 determine_affected_params = kwargs [ 'determine_affected_params' ]
- 60
- 61 # Uncertainties
- 62 poverty_bias = kwargs [ 'poverty_bias' ]
- 63 consumption_utility = kwargs [ 'consumption_utility' ]
- 64 discount_rate = kwargs [ 'discount_rate' ]
- 65 optimization_timestep = kwargs [ 'optimization_timestep' ]
- 66 income_and_expenditure_growth = kwargs [ 'income_and_expenditure_growth' ]
- 67
- 68 # Policy levers
- 69 try :
- 70 my_policy = kwargs [ 'my_policy' ]
- 71 except :
- 72 # If a policy is not provided, use the default policy
- 73 my_policy = 'all+0'
- 74
- 75 add_income_loss = kwargs [ 'add_income_loss' ]
- 76
- 77 # Outcomes
- 78 # Store outcomes in a dictionary, where the key is a district and value is a dictionary of outcomes
- 79 outcomes = {}
- 80
- 81 # Print statistics for debugging
- 82 print_statistics = kwargs [ 'print_statistics' ]
- 83
- 84 # Fix random seed for reproducibility
- 85 random_seed = kwargs [ 'random_seed' ]
- 86 random . seed ( random_seed )
- 87 np . random . seed ( random_seed )
- 88
- 89 # PIPELINE:
- 90 # 1. Load all damage
- 91 # 2. Load household survey
- 92 # 3. Select district
- 93 # 4. Get event damage, total asset stock, expected loss fraction
- 94 # 5. Calculate average productivity
- 95 # 6. Adjust assets and expenditure
- 96 # 7. Calculate PML
- 97 # 8. Estimate savings
- 98 # 9. Set vulnerability
- 99 # 10. Calculate exposure
-100 # 11. Determine affected
-101 # 12. Apply individual policy
-102 # 13. Run optimization
-103 # 14. Integrate wellbeing
-104 # 15. Prepare outcomes
-105 # 16. Get outcomes
-106
-107 # ---------------------- Run the model for each district --------------------- #
-108
-109 for district in districts :
-110 # Read household survey and asset damage files for a specific district
-111 event_damage , total_asset_stock , expected_loss_fraction = get_asset_damage (
-112 all_damage , scale , district , return_period , print_statistics )
-113
-114 households = select_district ( household_survey , district )
-115
-116 average_productivity = calculate_average_productivity (
-117 households , print_statistics )
-118
-119 # Model the impact of a disaster on households
-120 households = ( adjust_assets_and_expenditure ( households , total_asset_stock , poverty_line , indigence_line , print_statistics )
-121 . pipe ( calculate_pml , expected_loss_fraction , print_statistics )
-122 . pipe ( estimate_savings , saving_rate , estimate_savings_params )
-123 . pipe ( set_vulnerability , is_vulnerability_random , set_vulnerability_params )
-124 . pipe ( calculate_exposure , poverty_bias , calculate_exposure_params , print_statistics )
-125 . pipe ( determine_affected , determine_affected_params ))
-126
-127 # households['aesav'].hist()
-128 # plt.show()
-129
-130 # Apply a policy
-131 households , affected_households = apply_individual_policy (
-132 households , my_policy )
-133
-134 # Calculate the impact and recovery
-135 # cash_transfer = {52: 1000, 208: 5000}
-136 cash_transfer = {}
-137 affected_households = ( run_optimization ( affected_households , consumption_utility , discount_rate , average_productivity , optimization_timestep , n_years )
-138 . pipe ( integrate_wellbeing , consumption_utility , discount_rate , income_and_expenditure_growth , average_productivity , poverty_line , n_years , add_income_loss , cash_transfer ))
-139
-140 # Add columns of affected households to the original households dataframe
-141 households = add_columns ( households , affected_households )
-142 # Get outcomes
-143 array_outcomes = np . array ( list ( get_outcomes (
-144 households , event_damage , total_asset_stock , expected_loss_fraction , average_productivity , n_years ) . values ()))
-145
-146 # * To check whether we have different households affected in different runs
-147 # if district == 'Castries':
-148 # affected_households.to_csv(f'affected_households_{random_seed}.csv')
-149
-150 outcomes [ district ] = array_outcomes
-151
-152 return outcomes
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/src/modules.html b/docs/src/modules.html
deleted file mode 100644
index a0050ed..0000000
--- a/docs/src/modules.html
+++ /dev/null
@@ -1,238 +0,0 @@
-
-
-
-
-
-
- src.modules API documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-src .modules
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/src/modules/households.html b/docs/src/modules/households.html
deleted file mode 100644
index 7e8bbd7..0000000
--- a/docs/src/modules/households.html
+++ /dev/null
@@ -1,1380 +0,0 @@
-
-
-
-
-
-
- src.modules.households API documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- View Source
-
- 1 import pandas as pd
- 2 import numpy as np
- 3
- 4
- 5 def duplicate_households ( household_survey : pd . DataFrame , min_households : int ) -> pd . DataFrame :
- 6 '''Duplicates households if the number of households is less than `min_households` threshold.
- 7
- 8 Args:
- 9 household_survey (pd.DataFrame): Household survey data.
- 10 min_households (int): Minimum number of households.
- 11
- 12 Returns:
- 13 pd.DataFrame: Household survey data with duplicated households.
- 14
- 15 Raises:
- 16 ValueError: If the total weights after duplication is not equal to the initial total weights.
- 17 '''
- 18
- 19 if len ( household_survey ) < min_households :
- 20 print (
- 21 f 'Number of households = { len ( household_survey ) } is less than the threshold = { min_households } ' )
- 22
- 23 initial_total_weights = household_survey [ 'popwgt' ] . sum ()
- 24
- 25 # Save the original household id
- 26 household_survey [ 'hhid_original' ] = household_survey [[ 'hhid' ]]
- 27
- 28 # Get random ids from the household data to be duplicated
- 29 ids = np . random . choice (
- 30 household_survey . index , min_households - len ( household_survey ), replace = True )
- 31 n_duplicates = pd . Series ( ids ) . value_counts () + 1
- 32 duplicates = household_survey . loc [ ids ]
- 33
- 34 # Adjust the weights of the duplicated households
- 35 duplicates [ 'popwgt' ] = duplicates [ 'popwgt' ] / n_duplicates
- 36
- 37 # Adjust the weights of the original households
- 38 household_survey . loc [ ids , 'popwgt' ] = household_survey . loc [ ids ,
- 39 'popwgt' ] / n_duplicates
- 40
- 41 # Combine the original and duplicated households
- 42 household_survey = pd . concat (
- 43 [ household_survey , duplicates ], ignore_index = True )
- 44
- 45 # Check if the total weights after duplication is equal to the initial total weights
- 46 # TODO: Allow for a small difference
- 47 weights_after_duplication = household_survey [ 'popwgt' ] . sum ()
- 48 if weights_after_duplication != initial_total_weights :
- 49 raise ValueError (
- 50 'Total weights after duplication is not equal to the initial total weights' )
- 51
- 52 household_survey . reset_index ( drop = True , inplace = True )
- 53 print (
- 54 f 'Number of households after duplication: { len ( household_survey ) } ' )
- 55 else :
- 56 return household_survey
- 57
- 58
- 59 def calculate_average_productivity ( households : pd . DataFrame , print_statistics : bool ) -> float :
- 60 '''Calculate average productivity as aeinc \ k_house_ae.
- 61
- 62 Args:
- 63 households (pd.DataFrame): Household survey data.
- 64 print_statistics (bool, optional): Whether to print the average productivity. Defaults to False.
- 65
- 66 Returns:
- 67 float: Average productivity.
- 68 '''
- 69 # DEFF: aeinc - some type of income
- 70 average_productivity = households [ 'aeinc' ] / households [ 'k_house_ae' ]
- 71
- 72 # ?: What's happening here?
- 73 # average_productivity = average_productivity.iloc[0]
- 74 average_productivity = np . nanmedian ( average_productivity )
- 75 if print_statistics :
- 76 print ( 'Average productivity of capital = ' +
- 77 str ( np . round ( average_productivity , 3 )))
- 78 return average_productivity
- 79
- 80
- 81 def adjust_assets_and_expenditure ( households : pd . DataFrame , total_asset_stock : float , poverty_line : float , indigence_line : float , print_statistics : bool ) -> pd . DataFrame :
- 82 '''Adjust assets and expenditure of household to match data of asset damage file.
- 83
- 84 There can be a mismatch between the data in the household survey and the of the asset damage.
- 85 The latest was created independently.
- 86
- 87 Args:
- 88 households (pd.DataFrame): Household survey data.
- 89 total_asset_stock (float): Total asset stock.
- 90 poverty_line (float): Poverty line.
- 91 indigence_line (float): Indigence line.
- 92 print_statistics (bool, optional): Whether to print the statistics. Defaults to False.
- 93
- 94 Returns:
- 95 pd.DataFrame: Household survey data with adjusted assets and expenditure.
- 96 '''
- 97 # k_house_ae - effective capital stock of the household
- 98 # aeexp - adult equivalent expenditure of a household (total)
- 99 # aeexp_house - data['hhexp_house'] (annual rent) / data['hhsize_ae']
-100 included_variables = [ 'k_house_ae' , 'aeexp' , 'aeexp_house' ]
-101
-102 # Save the initial values
-103 households [ 'k_house_ae_original' ] = households [ 'k_house_ae' ]
-104 households [ 'aeexp_original' ] = households [ 'aeexp' ]
-105 households [ 'aeexp_house_original' ] = households [ 'aeexp_house' ]
-106
-107 # Calculate the total asset in the survey
-108 total_asset_in_survey = households [[
-109 'popwgt' , 'k_house_ae' ]] . prod ( axis = 1 ) . sum ()
-110 households [ 'total_asset_in_survey' ] = total_asset_in_survey
-111
-112 # Calculate the scaling factor and adjust the variables
-113 scaling_factor = total_asset_stock / total_asset_in_survey
-114 households [ included_variables ] *= scaling_factor
-115 households [ 'poverty_line_adjusted' ] = poverty_line * scaling_factor
-116 households [ 'indigence_line_adjusted' ] = indigence_line * scaling_factor
-117
-118 if print_statistics :
-119 print ( 'Total asset in survey =' , ' {:,} ' . format (
-120 round ( total_asset_in_survey )))
-121 print ( 'Total asset in asset damage file =' ,
-122 ' {:,} ' . format ( round ( total_asset_stock )))
-123 print ( 'Scaling factor =' , round ( scaling_factor , 3 ))
-124
-125 return households
-126
-127
-128 def calculate_pml ( households : pd . DataFrame , expected_loss_fraction : float , print_statistics : bool ) -> pd . DataFrame :
-129 '''Calculate probable maximum loss as a product of population weight, effective capital stock and expected loss fraction.
-130
-131 Args:
-132 households (pd.DataFrame): Household survey data.
-133 expected_loss_fraction (float): Expected loss fraction.
-134 print_statistics (bool, optional): Whether to print the statistics. Defaults to False.
-135
-136 Returns:
-137 pd.DataFrame: Household survey data with probable maximum loss.
-138 '''
-139 # DEF: keff - effective capital stock
-140 # DEF: pml - probable maximum loss
-141 # DEF: popwgt - population weight of each household
-142 households [ 'keff' ] = households [ 'k_house_ae' ] . copy ()
-143 pml = households [[ 'popwgt' , 'keff' ]] . prod (
-144 axis = 1 ) . sum () * expected_loss_fraction
-145 households [ 'pml' ] = pml
-146 if print_statistics :
-147 print ( 'Probable maximum loss (total) : ' , ' {:,} ' . format ( round ( pml )))
-148 return households
-149
-150
-151 def select_district ( household_survey : pd . DataFrame , district : str ) -> pd . DataFrame :
-152 '''Select households for a specific district.'''
-153 return household_survey [ household_survey [ 'district' ] == district ] . copy ()
-154
-155
-156 def estimate_savings ( households : pd . DataFrame , saving_rate : float , estimate_savings_params : dict ) -> pd . DataFrame :
-157 '''Estimate savings of households.
-158
-159 We assume that savings are a product of expenditure and saving rate with Gaussian noise.
-160
-161 Args:
-162 households (pd.DataFrame): Household survey data for a specific district.
-163 saving_rate (float): Saving rate.
-164 estimate_savings_params (dict): Parameters for estimating savings function.
-165
-166 Returns:
-167 pd.DataFrame: Household survey data with estimated savings.
-168 '''
-169 # * Expenditure & savings information for Saint Lucia https://www.ceicdata.com/en/saint-lucia/lending-saving-and-deposit-rates-annual/lc-savings-rate
-170
-171 # Savings are a product of expenditure and saving rate
-172 x = households . eval ( f 'aeexp* { saving_rate } ' )
-173
-174 # Get the mean of the noise with uniform distribution
-175 mean_noise_low = estimate_savings_params [ 'mean_noise_low' ] # default 0
-176 mean_noise_high = estimate_savings_params [ 'mean_noise_high' ] # default 5
-177
-178 if estimate_savings_params [ 'mean_noise_distribution' ] == 'uniform' :
-179 loc = np . random . uniform ( mean_noise_low , mean_noise_high )
-180 else :
-181 raise ValueError ( "Only uniform distribution is supported yet." )
-182
-183 # Get the scale
-184 scale = estimate_savings_params [ 'noise_scale' ] # default 2.5
-185 size = households . shape [ 0 ]
-186 clip_min = estimate_savings_params [ 'savings_clip_min' ] # default 0.1
-187 clip_max = estimate_savings_params [ 'savings_clip_max' ] # default 1.0
-188
-189 # Calculate savings with normal noise
-190 # !: aesav can go to 0 and above 1 because of the mean noise and loc
-191 # !: See `verification.ipynb` for more details
-192 if estimate_savings_params [ 'noise_distribution' ] == 'normal' :
-193 households [ 'aesav' ] = x * \
-194 np . random . normal ( loc , scale , size ) . round (
-195 2 ) . clip ( min = clip_min , max = clip_max )
-196 else :
-197 ValueError ( "Only normal distribution is supported yet." )
-198
-199 return households
-200
-201
-202 def set_vulnerability ( households : pd . DataFrame , is_vulnerability_random : bool , set_vulnerability_params : dict ) -> pd . DataFrame :
-203 '''Set vulnerability of households.
-204
-205 Vulnerability can be random or based on `v_init` with uniform noise.
-206
-207 Args:
-208 households (pd.DataFrame): Household survey data for a specific district.
-209 is_vulnerability_random (bool): If True, vulnerability is random.
-210
-211 Returns:
-212 pd.DataFrame: Household survey data with assigned vulnerability.
-213
-214 Raises:
-215 ValueError: If the distribution is not supported.
-216 '''
-217
-218 # If vulnerability is random, then draw from the uniform distribution
-219 if is_vulnerability_random :
-220 # default 0.01
-221 low = set_vulnerability_params [ 'vulnerability_random_low' ]
-222 # default 0.90
-223 high = set_vulnerability_params [ 'vulnerability_random_high' ]
-224 if set_vulnerability_params [ 'vulnerability_random_distribution' ] == 'uniform' :
-225 households [ 'v' ] = np . random . uniform ( low , high , households . shape [ 0 ])
-226 else :
-227 raise ValueError ( "Only uniform distribution is supported yet." )
-228
-229 # If vulnerability is not random, use v_init as a starting point and add some noise
-230 # ?: What is the point of adding the noise to the v_init if we cap it anyhow
-231 else :
-232 # default 0.6
-233 low = set_vulnerability_params [ 'vulnerability_initial_low' ]
-234 # default 1.4
-235 high = set_vulnerability_params [ 'vulnerability_initial_high' ]
-236 # v - actual vulnerability
-237 # v_init - initial vulnerability
-238 if set_vulnerability_params [ 'vulnerability_initial_distribution' ] == 'uniform' :
-239 households [ 'v' ] = households [ 'v_init' ] * \
-240 np . random . uniform ( low , high , households . shape [ 0 ])
-241 else :
-242 raise ValueError ( "Only uniform distribution is supported yet." )
-243
-244 # default 0.95
-245 vulnerability_threshold = set_vulnerability_params [ 'vulnerability_initial_threshold' ]
-246
-247 # If vulnerability turned out to be (drawn) is above the threshold, set it to the threshold
-248 households . loc [ households [ 'v' ] >
-249 vulnerability_threshold , 'v' ] = vulnerability_threshold
-250
-251 return households
-252
-253
-254 def calculate_exposure ( households : pd . DataFrame , poverty_bias : float , calculate_exposure_params : dict , print_statistics : bool ) -> pd . DataFrame :
-255 '''Calculate exposure of households.
-256
-257 Exposure is a function of poverty bias, effective capital stock,
-258 vulnerability and probable maximum loss.
-259
-260 Args:
-261 households (pd.DataFrame): Household survey data for a specific district.
-262 poverty_bias (float): Poverty bias.
-263 calculate_exposure_params (dict): Parameters for calculating exposure function.
-264 print_statistics (bool): If True, print statistics.
-265
-266 Returns:
-267 pd.DataFrame: Household survey data with calculated exposure.
-268 '''
-269 pml = households [ 'pml' ] . iloc [ 0 ]
-270
-271 # Random value for poverty bias
-272 if poverty_bias == 'random' :
-273 # default 0.5
-274 low = calculate_exposure_params [ 'poverty_bias_random_low' ]
-275 # default 1.5
-276 high = calculate_exposure_params [ 'poverty_bias_random_high' ]
-277 if calculate_exposure_params [ 'poverty_bias_random_distribution' ] == 'uniform' :
-278 povbias = np . random . uniform ( low , high )
-279 else :
-280 raise ValueError ( "Only uniform distribution is supported yet." )
-281 else :
-282 povbias = poverty_bias
-283
-284 # Set poverty bias to 1 for all households
-285 households [ 'poverty_bias' ] = 1
-286
-287 # Set poverty bias to povbias for poor households
-288 households . loc [ households [ 'is_poor' ] == True , 'poverty_bias' ] = povbias
-289
-290 # DEFF: keff - effective capital stock
-291 delimiter = households [[ 'keff' , 'v' , 'poverty_bias' , 'popwgt' ]] . prod (
-292 axis = 1 ) . sum ()
-293
-294 # ?: fa - fraction affected?
-295 fa0 = pml / delimiter
-296
-297 # Print delimiter and fa0 with commas for thousands
-298 if print_statistics :
-299 print ( 'PML: ' , ' {:,} ' . format ( round ( pml , 2 )))
-300 print ( 'Delimiter: ' , ' {:,} ' . format ( round ( delimiter , 2 )))
-301 print ( 'f0: ' , ' {:,} ' . format ( round ( fa0 , 2 )))
-302
-303 households [ 'fa' ] = fa0 * households [[ 'poverty_bias' ]]
-304 households . drop ( 'poverty_bias' , axis = 1 , inplace = True )
-305 return households
-306
-307
-308 def determine_affected ( households : pd . DataFrame , determine_affected_params : dict ) -> tuple :
-309 '''Determines affected households.
-310
-311 We assume that all households have the same probability of being affected,
-312 but based on `fa` calculated in `calculate_exposure`.
-313
-314 Args:
-315 households (pd.DataFrame): Household survey data for a specific district.
-316 determine_affected_params (dict): Parameters for determining affected households function.
-317
-318 Returns:
-319 tuple: Household survey data with determined affected households and asset loss for each household.
-320
-321 Raises:
-322 ValueError: If total asset is less than PML.
-323 ValueError: If no mask was found.
-324 '''
-325 # Get PML, it is the same for all households
-326 pml = households [ 'pml' ] . iloc [ 0 ]
-327
-328 # Allow for a relatively small error
-329 delta = pml * determine_affected_params [ 'delta_pct' ] # default 0.025
-330
-331 # Check if total asset is less than PML
-332 total_asset = households [[ 'keff' , 'popwgt' ]] . prod ( axis = 1 ) . sum ()
-333 if total_asset < pml :
-334 raise ValueError (
-335 'Total asset is less than PML.' )
-336
-337 low = determine_affected_params [ 'low' ] # default 0
-338 high = determine_affected_params [ 'high' ] # default 1
-339
-340 # Generate multiple boolean masks at once
-341 num_masks = determine_affected_params [ 'num_masks' ] # default 2000
-342 masks = np . random . uniform (
-343 low , high , ( num_masks , households . shape [ 0 ])) <= households [ 'fa' ] . values
-344
-345 # Compute total_asset_loss for each mask
-346 asset_losses = (
-347 masks * households [[ 'keff' , 'v' , 'popwgt' ]] . values . prod ( axis = 1 )) . sum ( axis = 1 )
-348
-349 # Find the first mask that yields a total_asset_loss within the desired range
-350 mask_index = np . where (( asset_losses >= pml - delta ) &
-351 ( asset_losses <= pml + delta ))
-352
-353 # Raise an error if no mask was found
-354 if mask_index is None :
-355 raise ValueError (
-356 f 'Cannot find affected households in { num_masks } iterations.' )
-357 else :
-358 try :
-359 mask_index = mask_index [ 0 ][ 0 ]
-360 except :
-361 print ( 'mask_index: ' , mask_index )
-362
-363 chosen_mask = masks [ mask_index ]
-364
-365 # Assign the chosen mask to the 'is_affected' column of the DataFrame
-366 households [ 'is_affected' ] = chosen_mask
-367
-368 # Save the asset loss for each household
-369 households [ 'asset_loss' ] = households . loc [ households [ 'is_affected' ], [
-370 'keff' , 'v' , 'popwgt' ]] . prod ( axis = 1 ) . round ( 2 )
-371 households [ 'asset_loss' ] = households [ 'asset_loss' ] . fillna ( 0 )
-372
-373 return households
-374
-375
-376 def apply_individual_policy ( households : pd . DataFrame , my_policy : str ) -> tuple :
-377 '''Apply a policy to a specific target group.
-378
-379 Args:
-380 households (pd.DataFrame): Household survey data for a specific district.
-381 my_policy (str): Policy to apply. The structure of the policy is `target_group`+`top_up` in a single string. `target_group` can be `all`, `poor`, `poor_near_poor1.25`, `poor_near_poor2.0`, and the `top_up` 0, 10, 30 or 50.
-382
-383 Returns:
-384 tuple: Household survey data with applied policy and affected households.
-385 '''
-386
-387 poverty_line_adjusted = households [ 'poverty_line_adjusted' ] . iloc [ 0 ]
-388
-389 target_group , top_up = my_policy . split ( '+' )
-390 top_up = float ( top_up )
-391
-392 # Select a target group
-393 if target_group == 'all' :
-394 beneficiaries = households [ 'is_affected' ] == True
-395
-396 # * If the target group is poor, the policy won't decrease the number of new poor
-397 elif target_group == 'poor' :
-398 beneficiaries = ( households [ 'is_affected' ] == True ) & (
-399 households [ 'is_poor' ] == True )
-400
-401 elif target_group == 'poor_near_poor1.25' :
-402 poor_affected = ( households [ 'is_affected' ] == True ) & (
-403 households [ 'is_poor' ] == True )
-404 near_poor_affected = ( households [ 'is_affected' ] == True ) & (
-405 households [ 'is_poor' ] == False ) & ( households [ 'aeexp' ] < 1.25 * poverty_line_adjusted )
-406 beneficiaries = poor_affected | near_poor_affected
-407
-408 elif target_group == 'poor_near_poor2.0' :
-409 poor_affected = ( households [ 'is_affected' ] == True ) & (
-410 households [ 'is_poor' ] == True )
-411 near_poor_affected = ( households [ 'is_affected' ] == True ) & (
-412 households [ 'is_poor' ] == False ) & ( households [ 'aeexp' ] < 2 * poverty_line_adjusted )
-413 beneficiaries = poor_affected | near_poor_affected
-414
-415 # * Here we have to decide to what to add to aeexp or aesav
-416 households . loc [ beneficiaries ,
-417 'aesav' ] += households . loc [ beneficiaries ] . eval ( 'keff*v' ) * top_up / 100
-418
-419 # Select columns of interest
-420 columns_of_interest = [ 'hhid' , 'popwgt' , 'own_rent' , 'quintile' , 'aeexp' ,
-421 'aeexp_house' , 'keff' , 'v' , 'aesav' , 'aesoc' , 'delta_tax_safety' ]
-422 affected_households = households . loc [ households [ 'is_affected' ],
-423 columns_of_interest ] . copy ()
-424 return households , affected_households
-
-
-
-
-
-
-
-
- def
- duplicate_households ( household_survey : pandas . core . frame . DataFrame , min_households : int ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 6 def duplicate_households ( household_survey : pd . DataFrame , min_households : int ) -> pd . DataFrame :
- 7 '''Duplicates households if the number of households is less than `min_households` threshold.
- 8
- 9 Args:
-10 household_survey (pd.DataFrame): Household survey data.
-11 min_households (int): Minimum number of households.
-12
-13 Returns:
-14 pd.DataFrame: Household survey data with duplicated households.
-15
-16 Raises:
-17 ValueError: If the total weights after duplication is not equal to the initial total weights.
-18 '''
-19
-20 if len ( household_survey ) < min_households :
-21 print (
-22 f 'Number of households = { len ( household_survey ) } is less than the threshold = { min_households } ' )
-23
-24 initial_total_weights = household_survey [ 'popwgt' ] . sum ()
-25
-26 # Save the original household id
-27 household_survey [ 'hhid_original' ] = household_survey [[ 'hhid' ]]
-28
-29 # Get random ids from the household data to be duplicated
-30 ids = np . random . choice (
-31 household_survey . index , min_households - len ( household_survey ), replace = True )
-32 n_duplicates = pd . Series ( ids ) . value_counts () + 1
-33 duplicates = household_survey . loc [ ids ]
-34
-35 # Adjust the weights of the duplicated households
-36 duplicates [ 'popwgt' ] = duplicates [ 'popwgt' ] / n_duplicates
-37
-38 # Adjust the weights of the original households
-39 household_survey . loc [ ids , 'popwgt' ] = household_survey . loc [ ids ,
-40 'popwgt' ] / n_duplicates
-41
-42 # Combine the original and duplicated households
-43 household_survey = pd . concat (
-44 [ household_survey , duplicates ], ignore_index = True )
-45
-46 # Check if the total weights after duplication is equal to the initial total weights
-47 # TODO: Allow for a small difference
-48 weights_after_duplication = household_survey [ 'popwgt' ] . sum ()
-49 if weights_after_duplication != initial_total_weights :
-50 raise ValueError (
-51 'Total weights after duplication is not equal to the initial total weights' )
-52
-53 household_survey . reset_index ( drop = True , inplace = True )
-54 print (
-55 f 'Number of households after duplication: { len ( household_survey ) } ' )
-56 else :
-57 return household_survey
-
-
-
- Duplicates households if the number of households is less than min_households
threshold.
-
-
Args:
- household_survey (pd.DataFrame): Household survey data.
- min_households (int): Minimum number of households.
-
-
Returns:
- pd.DataFrame: Household survey data with duplicated households.
-
-
Raises:
- ValueError: If the total weights after duplication is not equal to the initial total weights.
-
-
-
-
-
-
-
-
- def
- calculate_average_productivity (households : pandas . core . frame . DataFrame , print_statistics : bool ) -> float :
-
- View Source
-
-
-
- 60 def calculate_average_productivity ( households : pd . DataFrame , print_statistics : bool ) -> float :
-61 '''Calculate average productivity as aeinc \ k_house_ae.
-62
-63 Args:
-64 households (pd.DataFrame): Household survey data.
-65 print_statistics (bool, optional): Whether to print the average productivity. Defaults to False.
-66
-67 Returns:
-68 float: Average productivity.
-69 '''
-70 # DEFF: aeinc - some type of income
-71 average_productivity = households [ 'aeinc' ] / households [ 'k_house_ae' ]
-72
-73 # ?: What's happening here?
-74 # average_productivity = average_productivity.iloc[0]
-75 average_productivity = np . nanmedian ( average_productivity )
-76 if print_statistics :
-77 print ( 'Average productivity of capital = ' +
-78 str ( np . round ( average_productivity , 3 )))
-79 return average_productivity
-
-
-
- Calculate average productivity as aeinc \ k_house_ae.
-
-
Args:
- households (pd.DataFrame): Household survey data.
- print_statistics (bool, optional): Whether to print the average productivity. Defaults to False.
-
-
Returns:
- float: Average productivity.
-
-
-
-
-
-
-
-
- def
- adjust_assets_and_expenditure ( households : pandas . core . frame . DataFrame , total_asset_stock : float , poverty_line : float , indigence_line : float , print_statistics : bool ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 82 def adjust_assets_and_expenditure ( households : pd . DataFrame , total_asset_stock : float , poverty_line : float , indigence_line : float , print_statistics : bool ) -> pd . DataFrame :
- 83 '''Adjust assets and expenditure of household to match data of asset damage file.
- 84
- 85 There can be a mismatch between the data in the household survey and the of the asset damage.
- 86 The latest was created independently.
- 87
- 88 Args:
- 89 households (pd.DataFrame): Household survey data.
- 90 total_asset_stock (float): Total asset stock.
- 91 poverty_line (float): Poverty line.
- 92 indigence_line (float): Indigence line.
- 93 print_statistics (bool, optional): Whether to print the statistics. Defaults to False.
- 94
- 95 Returns:
- 96 pd.DataFrame: Household survey data with adjusted assets and expenditure.
- 97 '''
- 98 # k_house_ae - effective capital stock of the household
- 99 # aeexp - adult equivalent expenditure of a household (total)
-100 # aeexp_house - data['hhexp_house'] (annual rent) / data['hhsize_ae']
-101 included_variables = [ 'k_house_ae' , 'aeexp' , 'aeexp_house' ]
-102
-103 # Save the initial values
-104 households [ 'k_house_ae_original' ] = households [ 'k_house_ae' ]
-105 households [ 'aeexp_original' ] = households [ 'aeexp' ]
-106 households [ 'aeexp_house_original' ] = households [ 'aeexp_house' ]
-107
-108 # Calculate the total asset in the survey
-109 total_asset_in_survey = households [[
-110 'popwgt' , 'k_house_ae' ]] . prod ( axis = 1 ) . sum ()
-111 households [ 'total_asset_in_survey' ] = total_asset_in_survey
-112
-113 # Calculate the scaling factor and adjust the variables
-114 scaling_factor = total_asset_stock / total_asset_in_survey
-115 households [ included_variables ] *= scaling_factor
-116 households [ 'poverty_line_adjusted' ] = poverty_line * scaling_factor
-117 households [ 'indigence_line_adjusted' ] = indigence_line * scaling_factor
-118
-119 if print_statistics :
-120 print ( 'Total asset in survey =' , ' {:,} ' . format (
-121 round ( total_asset_in_survey )))
-122 print ( 'Total asset in asset damage file =' ,
-123 ' {:,} ' . format ( round ( total_asset_stock )))
-124 print ( 'Scaling factor =' , round ( scaling_factor , 3 ))
-125
-126 return households
-
-
-
- Adjust assets and expenditure of household to match data of asset damage file.
-
-
There can be a mismatch between the data in the household survey and the of the asset damage.
-The latest was created independently.
-
-
Args:
- households (pd.DataFrame): Household survey data.
- total_asset_stock (float): Total asset stock.
- poverty_line (float): Poverty line.
- indigence_line (float): Indigence line.
- print_statistics (bool, optional): Whether to print the statistics. Defaults to False.
-
-
Returns:
- pd.DataFrame: Household survey data with adjusted assets and expenditure.
-
-
-
-
-
-
-
-
- def
- calculate_pml ( households : pandas . core . frame . DataFrame , expected_loss_fraction : float , print_statistics : bool ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 129 def calculate_pml ( households : pd . DataFrame , expected_loss_fraction : float , print_statistics : bool ) -> pd . DataFrame :
-130 '''Calculate probable maximum loss as a product of population weight, effective capital stock and expected loss fraction.
-131
-132 Args:
-133 households (pd.DataFrame): Household survey data.
-134 expected_loss_fraction (float): Expected loss fraction.
-135 print_statistics (bool, optional): Whether to print the statistics. Defaults to False.
-136
-137 Returns:
-138 pd.DataFrame: Household survey data with probable maximum loss.
-139 '''
-140 # DEF: keff - effective capital stock
-141 # DEF: pml - probable maximum loss
-142 # DEF: popwgt - population weight of each household
-143 households [ 'keff' ] = households [ 'k_house_ae' ] . copy ()
-144 pml = households [[ 'popwgt' , 'keff' ]] . prod (
-145 axis = 1 ) . sum () * expected_loss_fraction
-146 households [ 'pml' ] = pml
-147 if print_statistics :
-148 print ( 'Probable maximum loss (total) : ' , ' {:,} ' . format ( round ( pml )))
-149 return households
-
-
-
- Calculate probable maximum loss as a product of population weight, effective capital stock and expected loss fraction.
-
-
Args:
- households (pd.DataFrame): Household survey data.
- expected_loss_fraction (float): Expected loss fraction.
- print_statistics (bool, optional): Whether to print the statistics. Defaults to False.
-
-
Returns:
- pd.DataFrame: Household survey data with probable maximum loss.
-
-
-
-
-
-
-
-
- def
- select_district ( household_survey : pandas . core . frame . DataFrame , district : str ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 152 def select_district ( household_survey : pd . DataFrame , district : str ) -> pd . DataFrame :
-153 '''Select households for a specific district.'''
-154 return household_survey [ household_survey [ 'district' ] == district ] . copy ()
-
-
-
- Select households for a specific district.
-
-
-
-
-
-
-
-
- def
- estimate_savings ( households : pandas . core . frame . DataFrame , saving_rate : float , estimate_savings_params : dict ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 157 def estimate_savings ( households : pd . DataFrame , saving_rate : float , estimate_savings_params : dict ) -> pd . DataFrame :
-158 '''Estimate savings of households.
-159
-160 We assume that savings are a product of expenditure and saving rate with Gaussian noise.
-161
-162 Args:
-163 households (pd.DataFrame): Household survey data for a specific district.
-164 saving_rate (float): Saving rate.
-165 estimate_savings_params (dict): Parameters for estimating savings function.
-166
-167 Returns:
-168 pd.DataFrame: Household survey data with estimated savings.
-169 '''
-170 # * Expenditure & savings information for Saint Lucia https://www.ceicdata.com/en/saint-lucia/lending-saving-and-deposit-rates-annual/lc-savings-rate
-171
-172 # Savings are a product of expenditure and saving rate
-173 x = households . eval ( f 'aeexp* { saving_rate } ' )
-174
-175 # Get the mean of the noise with uniform distribution
-176 mean_noise_low = estimate_savings_params [ 'mean_noise_low' ] # default 0
-177 mean_noise_high = estimate_savings_params [ 'mean_noise_high' ] # default 5
-178
-179 if estimate_savings_params [ 'mean_noise_distribution' ] == 'uniform' :
-180 loc = np . random . uniform ( mean_noise_low , mean_noise_high )
-181 else :
-182 raise ValueError ( "Only uniform distribution is supported yet." )
-183
-184 # Get the scale
-185 scale = estimate_savings_params [ 'noise_scale' ] # default 2.5
-186 size = households . shape [ 0 ]
-187 clip_min = estimate_savings_params [ 'savings_clip_min' ] # default 0.1
-188 clip_max = estimate_savings_params [ 'savings_clip_max' ] # default 1.0
-189
-190 # Calculate savings with normal noise
-191 # !: aesav can go to 0 and above 1 because of the mean noise and loc
-192 # !: See `verification.ipynb` for more details
-193 if estimate_savings_params [ 'noise_distribution' ] == 'normal' :
-194 households [ 'aesav' ] = x * \
-195 np . random . normal ( loc , scale , size ) . round (
-196 2 ) . clip ( min = clip_min , max = clip_max )
-197 else :
-198 ValueError ( "Only normal distribution is supported yet." )
-199
-200 return households
-
-
-
- Estimate savings of households.
-
-
We assume that savings are a product of expenditure and saving rate with Gaussian noise.
-
-
Args:
- households (pd.DataFrame): Household survey data for a specific district.
- saving_rate (float): Saving rate.
- estimate_savings_params (dict): Parameters for estimating savings function.
-
-
Returns:
- pd.DataFrame: Household survey data with estimated savings.
-
-
-
-
-
-
-
-
- def
- set_vulnerability ( households : pandas . core . frame . DataFrame , is_vulnerability_random : bool , set_vulnerability_params : dict ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 203 def set_vulnerability ( households : pd . DataFrame , is_vulnerability_random : bool , set_vulnerability_params : dict ) -> pd . DataFrame :
-204 '''Set vulnerability of households.
-205
-206 Vulnerability can be random or based on `v_init` with uniform noise.
-207
-208 Args:
-209 households (pd.DataFrame): Household survey data for a specific district.
-210 is_vulnerability_random (bool): If True, vulnerability is random.
-211
-212 Returns:
-213 pd.DataFrame: Household survey data with assigned vulnerability.
-214
-215 Raises:
-216 ValueError: If the distribution is not supported.
-217 '''
-218
-219 # If vulnerability is random, then draw from the uniform distribution
-220 if is_vulnerability_random :
-221 # default 0.01
-222 low = set_vulnerability_params [ 'vulnerability_random_low' ]
-223 # default 0.90
-224 high = set_vulnerability_params [ 'vulnerability_random_high' ]
-225 if set_vulnerability_params [ 'vulnerability_random_distribution' ] == 'uniform' :
-226 households [ 'v' ] = np . random . uniform ( low , high , households . shape [ 0 ])
-227 else :
-228 raise ValueError ( "Only uniform distribution is supported yet." )
-229
-230 # If vulnerability is not random, use v_init as a starting point and add some noise
-231 # ?: What is the point of adding the noise to the v_init if we cap it anyhow
-232 else :
-233 # default 0.6
-234 low = set_vulnerability_params [ 'vulnerability_initial_low' ]
-235 # default 1.4
-236 high = set_vulnerability_params [ 'vulnerability_initial_high' ]
-237 # v - actual vulnerability
-238 # v_init - initial vulnerability
-239 if set_vulnerability_params [ 'vulnerability_initial_distribution' ] == 'uniform' :
-240 households [ 'v' ] = households [ 'v_init' ] * \
-241 np . random . uniform ( low , high , households . shape [ 0 ])
-242 else :
-243 raise ValueError ( "Only uniform distribution is supported yet." )
-244
-245 # default 0.95
-246 vulnerability_threshold = set_vulnerability_params [ 'vulnerability_initial_threshold' ]
-247
-248 # If vulnerability turned out to be (drawn) is above the threshold, set it to the threshold
-249 households . loc [ households [ 'v' ] >
-250 vulnerability_threshold , 'v' ] = vulnerability_threshold
-251
-252 return households
-
-
-
- Set vulnerability of households.
-
-
Vulnerability can be random or based on v_init
with uniform noise.
-
-
Args:
- households (pd.DataFrame): Household survey data for a specific district.
- is_vulnerability_random (bool): If True, vulnerability is random.
-
-
Returns:
- pd.DataFrame: Household survey data with assigned vulnerability.
-
-
Raises:
- ValueError: If the distribution is not supported.
-
-
-
-
-
-
-
-
- def
- calculate_exposure ( households : pandas . core . frame . DataFrame , poverty_bias : float , calculate_exposure_params : dict , print_statistics : bool ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 255 def calculate_exposure ( households : pd . DataFrame , poverty_bias : float , calculate_exposure_params : dict , print_statistics : bool ) -> pd . DataFrame :
-256 '''Calculate exposure of households.
-257
-258 Exposure is a function of poverty bias, effective capital stock,
-259 vulnerability and probable maximum loss.
-260
-261 Args:
-262 households (pd.DataFrame): Household survey data for a specific district.
-263 poverty_bias (float): Poverty bias.
-264 calculate_exposure_params (dict): Parameters for calculating exposure function.
-265 print_statistics (bool): If True, print statistics.
-266
-267 Returns:
-268 pd.DataFrame: Household survey data with calculated exposure.
-269 '''
-270 pml = households [ 'pml' ] . iloc [ 0 ]
-271
-272 # Random value for poverty bias
-273 if poverty_bias == 'random' :
-274 # default 0.5
-275 low = calculate_exposure_params [ 'poverty_bias_random_low' ]
-276 # default 1.5
-277 high = calculate_exposure_params [ 'poverty_bias_random_high' ]
-278 if calculate_exposure_params [ 'poverty_bias_random_distribution' ] == 'uniform' :
-279 povbias = np . random . uniform ( low , high )
-280 else :
-281 raise ValueError ( "Only uniform distribution is supported yet." )
-282 else :
-283 povbias = poverty_bias
-284
-285 # Set poverty bias to 1 for all households
-286 households [ 'poverty_bias' ] = 1
-287
-288 # Set poverty bias to povbias for poor households
-289 households . loc [ households [ 'is_poor' ] == True , 'poverty_bias' ] = povbias
-290
-291 # DEFF: keff - effective capital stock
-292 delimiter = households [[ 'keff' , 'v' , 'poverty_bias' , 'popwgt' ]] . prod (
-293 axis = 1 ) . sum ()
-294
-295 # ?: fa - fraction affected?
-296 fa0 = pml / delimiter
-297
-298 # Print delimiter and fa0 with commas for thousands
-299 if print_statistics :
-300 print ( 'PML: ' , ' {:,} ' . format ( round ( pml , 2 )))
-301 print ( 'Delimiter: ' , ' {:,} ' . format ( round ( delimiter , 2 )))
-302 print ( 'f0: ' , ' {:,} ' . format ( round ( fa0 , 2 )))
-303
-304 households [ 'fa' ] = fa0 * households [[ 'poverty_bias' ]]
-305 households . drop ( 'poverty_bias' , axis = 1 , inplace = True )
-306 return households
-
-
-
- Calculate exposure of households.
-
-
Exposure is a function of poverty bias, effective capital stock,
-vulnerability and probable maximum loss.
-
-
Args:
- households (pd.DataFrame): Household survey data for a specific district.
- poverty_bias (float): Poverty bias.
- calculate_exposure_params (dict): Parameters for calculating exposure function.
- print_statistics (bool): If True, print statistics.
-
-
Returns:
- pd.DataFrame: Household survey data with calculated exposure.
-
-
-
-
-
-
-
-
- def
- determine_affected ( households : pandas . core . frame . DataFrame , determine_affected_params : dict ) -> tuple :
-
- View Source
-
-
-
- 309 def determine_affected ( households : pd . DataFrame , determine_affected_params : dict ) -> tuple :
-310 '''Determines affected households.
-311
-312 We assume that all households have the same probability of being affected,
-313 but based on `fa` calculated in `calculate_exposure`.
-314
-315 Args:
-316 households (pd.DataFrame): Household survey data for a specific district.
-317 determine_affected_params (dict): Parameters for determining affected households function.
-318
-319 Returns:
-320 tuple: Household survey data with determined affected households and asset loss for each household.
-321
-322 Raises:
-323 ValueError: If total asset is less than PML.
-324 ValueError: If no mask was found.
-325 '''
-326 # Get PML, it is the same for all households
-327 pml = households [ 'pml' ] . iloc [ 0 ]
-328
-329 # Allow for a relatively small error
-330 delta = pml * determine_affected_params [ 'delta_pct' ] # default 0.025
-331
-332 # Check if total asset is less than PML
-333 total_asset = households [[ 'keff' , 'popwgt' ]] . prod ( axis = 1 ) . sum ()
-334 if total_asset < pml :
-335 raise ValueError (
-336 'Total asset is less than PML.' )
-337
-338 low = determine_affected_params [ 'low' ] # default 0
-339 high = determine_affected_params [ 'high' ] # default 1
-340
-341 # Generate multiple boolean masks at once
-342 num_masks = determine_affected_params [ 'num_masks' ] # default 2000
-343 masks = np . random . uniform (
-344 low , high , ( num_masks , households . shape [ 0 ])) <= households [ 'fa' ] . values
-345
-346 # Compute total_asset_loss for each mask
-347 asset_losses = (
-348 masks * households [[ 'keff' , 'v' , 'popwgt' ]] . values . prod ( axis = 1 )) . sum ( axis = 1 )
-349
-350 # Find the first mask that yields a total_asset_loss within the desired range
-351 mask_index = np . where (( asset_losses >= pml - delta ) &
-352 ( asset_losses <= pml + delta ))
-353
-354 # Raise an error if no mask was found
-355 if mask_index is None :
-356 raise ValueError (
-357 f 'Cannot find affected households in { num_masks } iterations.' )
-358 else :
-359 try :
-360 mask_index = mask_index [ 0 ][ 0 ]
-361 except :
-362 print ( 'mask_index: ' , mask_index )
-363
-364 chosen_mask = masks [ mask_index ]
-365
-366 # Assign the chosen mask to the 'is_affected' column of the DataFrame
-367 households [ 'is_affected' ] = chosen_mask
-368
-369 # Save the asset loss for each household
-370 households [ 'asset_loss' ] = households . loc [ households [ 'is_affected' ], [
-371 'keff' , 'v' , 'popwgt' ]] . prod ( axis = 1 ) . round ( 2 )
-372 households [ 'asset_loss' ] = households [ 'asset_loss' ] . fillna ( 0 )
-373
-374 return households
-
-
-
- Determines affected households.
-
-
We assume that all households have the same probability of being affected,
-but based on fa
calculated in calculate_exposure
.
-
-
Args:
- households (pd.DataFrame): Household survey data for a specific district.
- determine_affected_params (dict): Parameters for determining affected households function.
-
-
Returns:
- tuple: Household survey data with determined affected households and asset loss for each household.
-
-
Raises:
- ValueError: If total asset is less than PML.
- ValueError: If no mask was found.
-
-
-
-
-
-
-
-
- def
- apply_individual_policy (households : pandas . core . frame . DataFrame , my_policy : str ) -> tuple :
-
- View Source
-
-
-
- 377 def apply_individual_policy ( households : pd . DataFrame , my_policy : str ) -> tuple :
-378 '''Apply a policy to a specific target group.
-379
-380 Args:
-381 households (pd.DataFrame): Household survey data for a specific district.
-382 my_policy (str): Policy to apply. The structure of the policy is `target_group`+`top_up` in a single string. `target_group` can be `all`, `poor`, `poor_near_poor1.25`, `poor_near_poor2.0`, and the `top_up` 0, 10, 30 or 50.
-383
-384 Returns:
-385 tuple: Household survey data with applied policy and affected households.
-386 '''
-387
-388 poverty_line_adjusted = households [ 'poverty_line_adjusted' ] . iloc [ 0 ]
-389
-390 target_group , top_up = my_policy . split ( '+' )
-391 top_up = float ( top_up )
-392
-393 # Select a target group
-394 if target_group == 'all' :
-395 beneficiaries = households [ 'is_affected' ] == True
-396
-397 # * If the target group is poor, the policy won't decrease the number of new poor
-398 elif target_group == 'poor' :
-399 beneficiaries = ( households [ 'is_affected' ] == True ) & (
-400 households [ 'is_poor' ] == True )
-401
-402 elif target_group == 'poor_near_poor1.25' :
-403 poor_affected = ( households [ 'is_affected' ] == True ) & (
-404 households [ 'is_poor' ] == True )
-405 near_poor_affected = ( households [ 'is_affected' ] == True ) & (
-406 households [ 'is_poor' ] == False ) & ( households [ 'aeexp' ] < 1.25 * poverty_line_adjusted )
-407 beneficiaries = poor_affected | near_poor_affected
-408
-409 elif target_group == 'poor_near_poor2.0' :
-410 poor_affected = ( households [ 'is_affected' ] == True ) & (
-411 households [ 'is_poor' ] == True )
-412 near_poor_affected = ( households [ 'is_affected' ] == True ) & (
-413 households [ 'is_poor' ] == False ) & ( households [ 'aeexp' ] < 2 * poverty_line_adjusted )
-414 beneficiaries = poor_affected | near_poor_affected
-415
-416 # * Here we have to decide to what to add to aeexp or aesav
-417 households . loc [ beneficiaries ,
-418 'aesav' ] += households . loc [ beneficiaries ] . eval ( 'keff*v' ) * top_up / 100
-419
-420 # Select columns of interest
-421 columns_of_interest = [ 'hhid' , 'popwgt' , 'own_rent' , 'quintile' , 'aeexp' ,
-422 'aeexp_house' , 'keff' , 'v' , 'aesav' , 'aesoc' , 'delta_tax_safety' ]
-423 affected_households = households . loc [ households [ 'is_affected' ],
-424 columns_of_interest ] . copy ()
-425 return households , affected_households
-
-
-
- Apply a policy to a specific target group.
-
-
Args:
- households (pd.DataFrame): Household survey data for a specific district.
- my_policy (str): Policy to apply. The structure of the policy is target_group
+top_up
in a single string. target_group
can be all
, poor
, poor_near_poor1.25
, poor_near_poor2.0
, and the top_up
0, 10, 30 or 50.
-
-
Returns:
- tuple: Household survey data with applied policy and affected households.
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/src/modules/optimize.html b/docs/src/modules/optimize.html
deleted file mode 100644
index 34c0c88..0000000
--- a/docs/src/modules/optimize.html
+++ /dev/null
@@ -1,779 +0,0 @@
-
-
-
-
-
-
- src.modules.optimize API documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- View Source
-
- 1 import numpy as np
- 2 import pandas as pd
- 3 import pickle
- 4
- 5
- 6 def run_optimization ( affected_households : pd . DataFrame , consumption_utility : float , discount_rate : float , average_productivity : float , optimization_timestep : float , n_years : int ) -> pd . DataFrame :
- 7 '''This function calculates the recovery rate for each affected household.
- 8
- 9 Args:
- 10 affected_households (pd.DataFrame): A data frame containing the affected households.
- 11 consumption_utility (float): The coefficient of relative risk aversion.
- 12 discount_rate (float): The discount rate.
- 13 average_productivity (float): The average productivity.
- 14 optimization_timestep (float): The timestep for the optimization.
- 15 n_years (int): The number of years in the optimization algorithm.
- 16
- 17 Returns:
- 18 pd.DataFrame: A data frame containing the affected households with the recovery rate.
- 19 '''
- 20
- 21 # Set effective capital stock to zero for renters
- 22 affected_households . loc [ affected_households [ 'own_rent' ]
- 23 == 'rent' , 'keff' ] = 0 # V
- 24
- 25 # Prepare a data frame to store optimization results
- 26 optimization_results = pd . DataFrame ({ 'aeexp' : - 1 ,
- 27 'aeexp_house' : - 1 ,
- 28 'keff' : - 1 ,
- 29 'v' : - 1 ,
- 30 'aesav' : - 1 ,
- 31 'solution' : None ,
- 32 'bankrupt' : None }, index = [ 0 ])
- 33
- 34 optimization_results = optimization_results . reset_index ( drop = True ) . set_index (
- 35 [ 'aeexp' ,
- 36 'aeexp_house' ,
- 37 'keff' ,
- 38 'v' ,
- 39 'aesav' ])
- 40
- 41 # Calculate the recovery rate for each affected household
- 42 affected_households [ 'recovery_rate' ] = affected_households [ 'v' ] . apply (
- 43 lambda x : optimize_recovery_rate ( x , optimization_results , consumption_utility , discount_rate , average_productivity , optimization_timestep , n_years ))
- 44
- 45 # TODO: Check whether this has any impact on anything
- 46 # optimization_results = optimization_results.sort_index()
- 47
- 48 return affected_households
- 49
- 50
- 51 def optimize_recovery_rate ( x , optimization_results : pd . DataFrame , consumption_utility : float , discount_rate : float , average_productivity : float , optimization_timestep : float , n_years : int ) -> float :
- 52 try :
- 53 # Look for the existing solution
- 54 solution = optimization_results . loc [(
- 55 0 , 0 , 0 , round ( x , 3 ), round ( average_productivity , 3 )), 'solution' ]
- 56 return solution
- 57 except :
- 58 # No existing solution found, so we need to optimize
- 59 t_max_linspace = n_years # years
- 60 nsteps_linspace = 52 * t_max_linspace # total weeks
- 61 dt = t_max_linspace / nsteps_linspace
- 62
- 63 _lambda = 0
- 64 opt_step = optimization_timestep
- 65 last_dwdlambda = 0
- 66
- 67 while True :
- 68
- 69 dwdlambda = 0
- 70
- 71 for _t in np . linspace ( 0 , t_max_linspace , nsteps_linspace ):
- 72
- 73 part1 = average_productivity - \
- 74 ( average_productivity + _lambda ) * x * np . e ** ( - _lambda * _t )
- 75 part1 = part1 ** ( - consumption_utility )
- 76
- 77 part2 = _t * ( average_productivity + _lambda ) - 1
- 78
- 79 part3 = np . e ** ( - _t * ( discount_rate + _lambda ))
- 80
- 81 dwdlambda += part1 * part2 * part3 * dt
- 82
- 83 # !: All these do the same
- 84 if last_dwdlambda < 0 and dwdlambda > 0 :
- 85 optimization_results . loc [( 0 , 0 , 0 , round ( x , 3 ), round ( average_productivity , 3 )), [
- 86 'solution' , 'bankrupt' ]] = [ _lambda , False ]
- 87 optimization_results = optimization_results . sort_index ()
- 88 return _lambda
- 89
- 90 elif last_dwdlambda > 0 and dwdlambda < 0 :
- 91 optimization_results . loc [( 0 , 0 , 0 , round ( x , 3 ), round ( average_productivity , 3 )), [
- 92 'solution' , 'bankrupt' ]] = [ _lambda , False ]
- 93 optimization_results = optimization_results . sort_index ()
- 94 return _lambda
- 95
- 96 # !: That's why assigning more than 10 years does not work, we need to change 10 to `n_years`?
- 97 elif _lambda > 10 :
- 98 optimization_results . loc [( 0 , 0 , 0 , round ( x , 3 ), round ( average_productivity , 3 )), [
- 99 'solution' , 'bankrupt' ]] = [ _lambda , False ]
-100 optimization_results = optimization_results . sort_index ()
-101 return _lambda
-102
-103 else :
-104 last_dwdlambda = dwdlambda
-105 _lambda += opt_step
-106
-107
-108 def integrate_wellbeing ( affected_households : pd . DataFrame ,
-109 consumption_utility : float ,
-110 discount_rate : float ,
-111 income_and_expenditure_growth : float ,
-112 average_productivity : float ,
-113 poverty_line : float ,
-114 n_years : int ,
-115 add_income_loss : bool ,
-116 cash_transfer : dict = {},
-117 ) -> pd . DataFrame :
-118
-119 # We need to reset some columns to zero to start the integration
-120 columns = [ 'consumption_loss' , 'consumption_loss_NPV' , 'net_consumption_loss' ,
-121 'net_consumption_loss_NPV' , 'c_t' , 'w_final' , 'weeks_pov' , 'w_final2' ]
-122 affected_households [ columns ] = [ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ]
-123
-124 # Define the number of weeks given the number of years
-125 n_weeks = 52 * n_years
-126 dt = n_years / n_weeks
-127
-128 # * Store consumption recovery in a dict for verification and debugging purposes
-129 # consumption_recovery = {}
-130
-131 # We need to adjust the cash transfer to the timestep of the integration
-132 if cash_transfer != {}: # If there is a cash transfer
-133 cash_transfer_transformed = { np . linspace ( 0 , n_years , n_weeks )[
-134 t ]: cash_transfer [ t ] for t in list ( cash_transfer . keys ())}
-135 else :
-136 cash_transfer_transformed = {}
-137
-138 # Calculate the consumption loss for each affected household
-139 for _t in np . linspace ( 0 , n_years , n_weeks ):
-140 gfac = ( 1 + income_and_expenditure_growth ) ** _t
-141
-142 # TODO: Add an extra condition about to whom the transfer is given
-143 # A "dynamic policy"
-144 if _t in list ( cash_transfer_transformed . keys ()):
-145 affected_households [ 'aesav' ] += cash_transfer_transformed [ _t ]
-146
-147 # `c_t` is the consumption at time t
-148 # !: It seems that keff remains constant over time
-149 expenditure_growth = gfac * affected_households [ 'aeexp' ]
-150 exponential_multiplier = np . e ** (
-151 - affected_households [ 'recovery_rate' ] * _t )
-152 savings = gfac * \
-153 affected_households [ 'aesav' ] * affected_households [ 'recovery_rate' ]
-154 asset_damage = gfac * \
-155 affected_households [ 'v' ] * \
-156 affected_households [[ 'keff' , 'recovery_rate' ]] . prod ( axis = 1 )
-157
-158 # TODO: Make sure that `delta_tax_safety` is not 0
-159 income_loss = gfac * ( 1 - affected_households [ 'delta_tax_safety' ]) * \
-160 average_productivity * \
-161 affected_households [ 'keff' ] * affected_households [ 'v' ]
-162
-163 # Equation is as follows: consumption_loss = expenditure_growth + exponential_multiplier * (savings - asset_damage - income_loss)
-164
-165 if add_income_loss :
-166 affected_households [ 'c_t' ] = ( expenditure_growth +
-167 exponential_multiplier * ( savings - asset_damage - income_loss ))
-168 else :
-169 affected_households [ 'c_t' ] = ( expenditure_growth +
-170 exponential_multiplier * ( savings - asset_damage ))
-171
-172 # affected_households['c_t'] = (gfac * affected_households['aeexp'] # expenditure growth
-173
-174 # + np.e**(-affected_households['recovery_rate']*_t) # exponential multiplier
-175
-176 # * (gfac * affected_households['aesav'] * affected_households['recovery_rate'] # savings
-177 # - gfac * affected_households['v'] * affected_households[['keff', 'recovery_rate']].prod(axis=1))) # asset damage
-178
-179 # # - (1 - affected_households['delta_tax_safety']) # income loss
-180 # # * average_productivity * affected_households['keff']
-181 # # * affected_households['v']))
-182
-183 # `c_t_unaffected` is the consumption at time t if the household was not affected by the disaster
-184 affected_households [ 'c_t_unaffected' ] = gfac * \
-185 affected_households [ 'aeexp' ]
-186
-187 # TODO: Add a check to see whether the consumption goes below 0
-188
-189 # Consumption cannot be lower than 0
-190 affected_households . loc [ affected_households [ 'c_t' ] < 1 , 'c_t' ] = 1
-191
-192 # TODO: Add a check whether the consumption after hit by disaster should be lower than or equal to consumption before hit by disaster
-193
-194 # consumption after hit by disaster should be lower than or equal to consumption before hit by disaster
-195 affected_households . loc [ affected_households [ 'c_t' ] > affected_households [ 'c_t_unaffected' ],
-196 'c_t' ] = affected_households . loc [ affected_households [ 'c_t' ] > affected_households [ 'c_t_unaffected' ], 'c_t_unaffected' ]
-197
-198 # total (integrated) consumption loss
-199 affected_households [ 'consumption_loss' ] += dt * \
-200 ( affected_households [ 'c_t_unaffected' ] -
-201 affected_households [ 'c_t' ])
-202
-203 affected_households [ 'consumption_loss_NPV' ] += dt * \
-204 ( affected_households [ 'c_t_unaffected' ] -
-205 affected_households [ 'c_t' ]) * np . e ** ( - discount_rate * _t )
-206
-207 affected_households [ 'net_consumption_loss' ] += dt * \
-208 np . e ** ( - affected_households [ 'recovery_rate' ] * _t ) * \
-209 affected_households [ 'v' ] * gfac * \
-210 affected_households [ 'aeexp_house' ]
-211
-212 affected_households [ 'net_consumption_loss_NPV' ] += dt * \
-213 np . e ** ( - affected_households [ 'recovery_rate' ] * _t ) * affected_households [ 'v' ] * gfac * \
-214 affected_households [ 'aeexp_house' ] * \
-215 np . e ** ( - discount_rate * _t )
-216
-217 # Increase the number of weeks in poverty
-218 affected_households . loc [ affected_households [ 'c_t' ]
-219 < poverty_line , 'weeks_pov' ] += 1
-220
-221 # Integrated wellbeing
-222 affected_households [ 'w_final' ] += dt * ( affected_households [ 'c_t' ]) ** ( 1 - consumption_utility ) * \
-223 np . e ** ( - discount_rate * _t ) / ( 1 - consumption_utility )
-224
-225 # w_final2 version 02
-226 affected_households [ 'w_final2' ] += affected_households [ 'c_t_unaffected' ] ** ( 1 - consumption_utility ) / ( 1 - consumption_utility ) * dt * (
-227 ( 1 - (( affected_households [ 'c_t_unaffected' ] - affected_households [ 'c_t' ]) / affected_households [ 'c_t_unaffected' ]) * np . e ** ( - affected_households [ 'recovery_rate' ] * _t )) ** ( 1 - consumption_utility ) - 1 ) * np . e ** ( - discount_rate * _t )
-228
-229 # * Use to examine individual consumption recovery
-230 # Save consumption recovery value at the time _t
-231 # consumption_recovery[_t] = affected_households['c_t']
-232
-233 # Save consumption recovery as pickle file
-234 # with open('consumption_recovery.pickle', 'wb') as handle:
-235 # pickle.dump(consumption_recovery, handle, protocol=pickle.HIGHEST_PROTOCOL)
-236
-237 return affected_households
-
-
-
-
-
-
-
-
- def
- run_optimization ( affected_households : pandas . core . frame . DataFrame , consumption_utility : float , discount_rate : float , average_productivity : float , optimization_timestep : float , n_years : int ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 7 def run_optimization ( affected_households : pd . DataFrame , consumption_utility : float , discount_rate : float , average_productivity : float , optimization_timestep : float , n_years : int ) -> pd . DataFrame :
- 8 '''This function calculates the recovery rate for each affected household.
- 9
-10 Args:
-11 affected_households (pd.DataFrame): A data frame containing the affected households.
-12 consumption_utility (float): The coefficient of relative risk aversion.
-13 discount_rate (float): The discount rate.
-14 average_productivity (float): The average productivity.
-15 optimization_timestep (float): The timestep for the optimization.
-16 n_years (int): The number of years in the optimization algorithm.
-17
-18 Returns:
-19 pd.DataFrame: A data frame containing the affected households with the recovery rate.
-20 '''
-21
-22 # Set effective capital stock to zero for renters
-23 affected_households . loc [ affected_households [ 'own_rent' ]
-24 == 'rent' , 'keff' ] = 0 # V
-25
-26 # Prepare a data frame to store optimization results
-27 optimization_results = pd . DataFrame ({ 'aeexp' : - 1 ,
-28 'aeexp_house' : - 1 ,
-29 'keff' : - 1 ,
-30 'v' : - 1 ,
-31 'aesav' : - 1 ,
-32 'solution' : None ,
-33 'bankrupt' : None }, index = [ 0 ])
-34
-35 optimization_results = optimization_results . reset_index ( drop = True ) . set_index (
-36 [ 'aeexp' ,
-37 'aeexp_house' ,
-38 'keff' ,
-39 'v' ,
-40 'aesav' ])
-41
-42 # Calculate the recovery rate for each affected household
-43 affected_households [ 'recovery_rate' ] = affected_households [ 'v' ] . apply (
-44 lambda x : optimize_recovery_rate ( x , optimization_results , consumption_utility , discount_rate , average_productivity , optimization_timestep , n_years ))
-45
-46 # TODO: Check whether this has any impact on anything
-47 # optimization_results = optimization_results.sort_index()
-48
-49 return affected_households
-
-
-
- This function calculates the recovery rate for each affected household.
-
-
Args:
- affected_households (pd.DataFrame): A data frame containing the affected households.
- consumption_utility (float): The coefficient of relative risk aversion.
- discount_rate (float): The discount rate.
- average_productivity (float): The average productivity.
- optimization_timestep (float): The timestep for the optimization.
- n_years (int): The number of years in the optimization algorithm.
-
-
Returns:
- pd.DataFrame: A data frame containing the affected households with the recovery rate.
-
-
-
-
-
-
-
-
- def
- optimize_recovery_rate ( x , optimization_results : pandas . core . frame . DataFrame , consumption_utility : float , discount_rate : float , average_productivity : float , optimization_timestep : float , n_years : int ) -> float :
-
- View Source
-
-
-
- 52 def optimize_recovery_rate ( x , optimization_results : pd . DataFrame , consumption_utility : float , discount_rate : float , average_productivity : float , optimization_timestep : float , n_years : int ) -> float :
- 53 try :
- 54 # Look for the existing solution
- 55 solution = optimization_results . loc [(
- 56 0 , 0 , 0 , round ( x , 3 ), round ( average_productivity , 3 )), 'solution' ]
- 57 return solution
- 58 except :
- 59 # No existing solution found, so we need to optimize
- 60 t_max_linspace = n_years # years
- 61 nsteps_linspace = 52 * t_max_linspace # total weeks
- 62 dt = t_max_linspace / nsteps_linspace
- 63
- 64 _lambda = 0
- 65 opt_step = optimization_timestep
- 66 last_dwdlambda = 0
- 67
- 68 while True :
- 69
- 70 dwdlambda = 0
- 71
- 72 for _t in np . linspace ( 0 , t_max_linspace , nsteps_linspace ):
- 73
- 74 part1 = average_productivity - \
- 75 ( average_productivity + _lambda ) * x * np . e ** ( - _lambda * _t )
- 76 part1 = part1 ** ( - consumption_utility )
- 77
- 78 part2 = _t * ( average_productivity + _lambda ) - 1
- 79
- 80 part3 = np . e ** ( - _t * ( discount_rate + _lambda ))
- 81
- 82 dwdlambda += part1 * part2 * part3 * dt
- 83
- 84 # !: All these do the same
- 85 if last_dwdlambda < 0 and dwdlambda > 0 :
- 86 optimization_results . loc [( 0 , 0 , 0 , round ( x , 3 ), round ( average_productivity , 3 )), [
- 87 'solution' , 'bankrupt' ]] = [ _lambda , False ]
- 88 optimization_results = optimization_results . sort_index ()
- 89 return _lambda
- 90
- 91 elif last_dwdlambda > 0 and dwdlambda < 0 :
- 92 optimization_results . loc [( 0 , 0 , 0 , round ( x , 3 ), round ( average_productivity , 3 )), [
- 93 'solution' , 'bankrupt' ]] = [ _lambda , False ]
- 94 optimization_results = optimization_results . sort_index ()
- 95 return _lambda
- 96
- 97 # !: That's why assigning more than 10 years does not work, we need to change 10 to `n_years`?
- 98 elif _lambda > 10 :
- 99 optimization_results . loc [( 0 , 0 , 0 , round ( x , 3 ), round ( average_productivity , 3 )), [
-100 'solution' , 'bankrupt' ]] = [ _lambda , False ]
-101 optimization_results = optimization_results . sort_index ()
-102 return _lambda
-103
-104 else :
-105 last_dwdlambda = dwdlambda
-106 _lambda += opt_step
-
-
-
-
-
-
-
-
-
-
- def
- integrate_wellbeing ( affected_households : pandas . core . frame . DataFrame , consumption_utility : float , discount_rate : float , income_and_expenditure_growth : float , average_productivity : float , poverty_line : float , n_years : int , add_income_loss : bool , cash_transfer : dict = {} ) -> pandas . core . frame . DataFrame :
-
- View Source
-
-
-
- 109 def integrate_wellbeing ( affected_households : pd . DataFrame ,
-110 consumption_utility : float ,
-111 discount_rate : float ,
-112 income_and_expenditure_growth : float ,
-113 average_productivity : float ,
-114 poverty_line : float ,
-115 n_years : int ,
-116 add_income_loss : bool ,
-117 cash_transfer : dict = {},
-118 ) -> pd . DataFrame :
-119
-120 # We need to reset some columns to zero to start the integration
-121 columns = [ 'consumption_loss' , 'consumption_loss_NPV' , 'net_consumption_loss' ,
-122 'net_consumption_loss_NPV' , 'c_t' , 'w_final' , 'weeks_pov' , 'w_final2' ]
-123 affected_households [ columns ] = [ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ]
-124
-125 # Define the number of weeks given the number of years
-126 n_weeks = 52 * n_years
-127 dt = n_years / n_weeks
-128
-129 # * Store consumption recovery in a dict for verification and debugging purposes
-130 # consumption_recovery = {}
-131
-132 # We need to adjust the cash transfer to the timestep of the integration
-133 if cash_transfer != {}: # If there is a cash transfer
-134 cash_transfer_transformed = { np . linspace ( 0 , n_years , n_weeks )[
-135 t ]: cash_transfer [ t ] for t in list ( cash_transfer . keys ())}
-136 else :
-137 cash_transfer_transformed = {}
-138
-139 # Calculate the consumption loss for each affected household
-140 for _t in np . linspace ( 0 , n_years , n_weeks ):
-141 gfac = ( 1 + income_and_expenditure_growth ) ** _t
-142
-143 # TODO: Add an extra condition about to whom the transfer is given
-144 # A "dynamic policy"
-145 if _t in list ( cash_transfer_transformed . keys ()):
-146 affected_households [ 'aesav' ] += cash_transfer_transformed [ _t ]
-147
-148 # `c_t` is the consumption at time t
-149 # !: It seems that keff remains constant over time
-150 expenditure_growth = gfac * affected_households [ 'aeexp' ]
-151 exponential_multiplier = np . e ** (
-152 - affected_households [ 'recovery_rate' ] * _t )
-153 savings = gfac * \
-154 affected_households [ 'aesav' ] * affected_households [ 'recovery_rate' ]
-155 asset_damage = gfac * \
-156 affected_households [ 'v' ] * \
-157 affected_households [[ 'keff' , 'recovery_rate' ]] . prod ( axis = 1 )
-158
-159 # TODO: Make sure that `delta_tax_safety` is not 0
-160 income_loss = gfac * ( 1 - affected_households [ 'delta_tax_safety' ]) * \
-161 average_productivity * \
-162 affected_households [ 'keff' ] * affected_households [ 'v' ]
-163
-164 # Equation is as follows: consumption_loss = expenditure_growth + exponential_multiplier * (savings - asset_damage - income_loss)
-165
-166 if add_income_loss :
-167 affected_households [ 'c_t' ] = ( expenditure_growth +
-168 exponential_multiplier * ( savings - asset_damage - income_loss ))
-169 else :
-170 affected_households [ 'c_t' ] = ( expenditure_growth +
-171 exponential_multiplier * ( savings - asset_damage ))
-172
-173 # affected_households['c_t'] = (gfac * affected_households['aeexp'] # expenditure growth
-174
-175 # + np.e**(-affected_households['recovery_rate']*_t) # exponential multiplier
-176
-177 # * (gfac * affected_households['aesav'] * affected_households['recovery_rate'] # savings
-178 # - gfac * affected_households['v'] * affected_households[['keff', 'recovery_rate']].prod(axis=1))) # asset damage
-179
-180 # # - (1 - affected_households['delta_tax_safety']) # income loss
-181 # # * average_productivity * affected_households['keff']
-182 # # * affected_households['v']))
-183
-184 # `c_t_unaffected` is the consumption at time t if the household was not affected by the disaster
-185 affected_households [ 'c_t_unaffected' ] = gfac * \
-186 affected_households [ 'aeexp' ]
-187
-188 # TODO: Add a check to see whether the consumption goes below 0
-189
-190 # Consumption cannot be lower than 0
-191 affected_households . loc [ affected_households [ 'c_t' ] < 1 , 'c_t' ] = 1
-192
-193 # TODO: Add a check whether the consumption after hit by disaster should be lower than or equal to consumption before hit by disaster
-194
-195 # consumption after hit by disaster should be lower than or equal to consumption before hit by disaster
-196 affected_households . loc [ affected_households [ 'c_t' ] > affected_households [ 'c_t_unaffected' ],
-197 'c_t' ] = affected_households . loc [ affected_households [ 'c_t' ] > affected_households [ 'c_t_unaffected' ], 'c_t_unaffected' ]
-198
-199 # total (integrated) consumption loss
-200 affected_households [ 'consumption_loss' ] += dt * \
-201 ( affected_households [ 'c_t_unaffected' ] -
-202 affected_households [ 'c_t' ])
-203
-204 affected_households [ 'consumption_loss_NPV' ] += dt * \
-205 ( affected_households [ 'c_t_unaffected' ] -
-206 affected_households [ 'c_t' ]) * np . e ** ( - discount_rate * _t )
-207
-208 affected_households [ 'net_consumption_loss' ] += dt * \
-209 np . e ** ( - affected_households [ 'recovery_rate' ] * _t ) * \
-210 affected_households [ 'v' ] * gfac * \
-211 affected_households [ 'aeexp_house' ]
-212
-213 affected_households [ 'net_consumption_loss_NPV' ] += dt * \
-214 np . e ** ( - affected_households [ 'recovery_rate' ] * _t ) * affected_households [ 'v' ] * gfac * \
-215 affected_households [ 'aeexp_house' ] * \
-216 np . e ** ( - discount_rate * _t )
-217
-218 # Increase the number of weeks in poverty
-219 affected_households . loc [ affected_households [ 'c_t' ]
-220 < poverty_line , 'weeks_pov' ] += 1
-221
-222 # Integrated wellbeing
-223 affected_households [ 'w_final' ] += dt * ( affected_households [ 'c_t' ]) ** ( 1 - consumption_utility ) * \
-224 np . e ** ( - discount_rate * _t ) / ( 1 - consumption_utility )
-225
-226 # w_final2 version 02
-227 affected_households [ 'w_final2' ] += affected_households [ 'c_t_unaffected' ] ** ( 1 - consumption_utility ) / ( 1 - consumption_utility ) * dt * (
-228 ( 1 - (( affected_households [ 'c_t_unaffected' ] - affected_households [ 'c_t' ]) / affected_households [ 'c_t_unaffected' ]) * np . e ** ( - affected_households [ 'recovery_rate' ] * _t )) ** ( 1 - consumption_utility ) - 1 ) * np . e ** ( - discount_rate * _t )
-229
-230 # * Use to examine individual consumption recovery
-231 # Save consumption recovery value at the time _t
-232 # consumption_recovery[_t] = affected_households['c_t']
-233
-234 # Save consumption recovery as pickle file
-235 # with open('consumption_recovery.pickle', 'wb') as handle:
-236 # pickle.dump(consumption_recovery, handle, protocol=pickle.HIGHEST_PROTOCOL)
-237
-238 return affected_households
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/experiments/config_manager.py b/experiments/config_manager.py
deleted file mode 100644
index 3365cce..0000000
--- a/experiments/config_manager.py
+++ /dev/null
@@ -1,102 +0,0 @@
-import yaml
-from pathlib import Path
-
-
-def load_config(country: str, return_period: int, disaster_type: str, is_conflict: bool = False) -> dict:
- '''Load configuration for the specified case country.
-
- Args:
- country (str): The country for which to load the configuration.
- return_period (int): The return period for the disaster.
- disaster_type (str): The type of disaster.
- is_conflict (bool): Whether the country is in conflict.
-
- Returns:
- dict: The configuration for the specified case country.
- '''
-
- config_path = Path(f"../config/{country}.yaml")
-
- if not config_path.exists():
- raise FileNotFoundError(
- f"Config file for {country} not found at {config_path}")
-
- with open(config_path, "r") as file:
- config = yaml.safe_load(file)
-
- check_config_parameters(config)
-
- config['constants']['return_period'] = return_period
- config['constants']['disaster_type'] = disaster_type
-
- if is_conflict:
- config['constants']['is_conflict'] = True
- else:
- config['constants']['is_conflict'] = False
-
- return config
-
-def check_config_parameters(config: dict) -> None:
- '''Check if the configuration parameters are valid.
-
- Args:
- config (dict): The configuration to check.
-
- Returns:
- None
-
- Raises:
- ValueError: If the configuration parameters are not valid.
- '''
- return_periods = [10, 50, 100, 250, 500, 1000]
- disaster_types = ['hurricane', 'flood']
-
- if 'return_period' not in config['constants']:
- raise ValueError("Return period not specified in configuration.")
-
- if 'disaster_type' not in config['constants']:
- raise ValueError("Disaster type not specified in configuration.")
-
- if 'return_period' not in return_periods:
- raise ValueError(
- f"Return period {config['constants']['return_period']} not in available return periods: {return_periods}")
-
- if 'disaster_type' not in disaster_types:
- raise ValueError(
- f"Disaster type {config['constants']['disaster_type']} not in available disaster types: ['hurricane', 'flood']")
-
- neccessary_parameters = ['country', 'avg_prod', 'inc_exp_growth', 'cons_util', 'disc_rate', 'disaster_type', 'calc_exposure_params', 'identify_aff_params', 'add_inc_loss', 'pov_bias', 'lambda_incr', 'yrs_to_rec', 'rnd_inc_params', 'rnd_sav_params', 'rnd_rent_params', 'rnd_house_vuln_params', 'min_households', 'atol', 'save_households', 'save_consumption_recovery', 'regions', 'levers', 'uncertainties']
- exposure_neccessary_parameters = ['distr', 'high', 'low']
- identify_aff_neccessary_parameters = ['delta_pct', 'distr', 'high', 'low', 'num_masks']
- rnd_inc_neccessary_parameters = ['randomize', 'distr', 'delta']
- rnd_sav_neccessary_parameters = ['randomize', 'distr', 'avg', 'delta']
- rnd_rent_neccessary_parameters = ['randomize', 'distr', 'avg', 'delta']
- rnd_house_vuln_neccessary_parameters = ['randomize', 'distr', 'low', 'high', 'min_thresh', 'max_thresh']
-
- for parameter in neccessary_parameters:
- if parameter not in config['constants']:
- raise ValueError(f"Parameter {parameter} not found in configuration.")
-
- for parameter in exposure_neccessary_parameters:
- if parameter not in config['constants']['calc_exposure_params']:
- raise ValueError(f"Parameter {parameter} not found in calc_exposure_params.")
-
- for parameter in identify_aff_neccessary_parameters:
- if parameter not in config['constants']['identify_aff_params']:
- raise ValueError(f"Parameter {parameter} not found in identify_aff_params.")
-
- for parameter in rnd_inc_neccessary_parameters:
- if parameter not in config['constants']['rnd_inc_params']:
- raise ValueError(f"Parameter {parameter} not found in rnd_inc_params.")
-
- for parameter in rnd_sav_neccessary_parameters:
- if parameter not in config['constants']['rnd_sav_params']:
- raise ValueError(f"Parameter {parameter} not found in rnd_sav_params.")
-
- for parameter in rnd_rent_neccessary_parameters:
- if parameter not in config['constants']['rnd_rent_params']:
- raise ValueError(f"Parameter {parameter} not found in rnd_rent_params.")
-
- for parameter in rnd_house_vuln_neccessary_parameters:
- if parameter not in config['constants']['rnd_house_vuln_params']:
- raise ValueError(f"Parameter {parameter} not found in rnd_house_vuln_params.")
\ No newline at end of file
diff --git a/experiments/experiment_runner.py b/experiments/experiment_runner.py
deleted file mode 100644
index eb7bb03..0000000
--- a/experiments/experiment_runner.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from pathlib import Path
-from ema_workbench import perform_experiments, MultiprocessingEvaluator, save_results, Model
-
-
-def run_experiments(experimental_setup: dict) -> None:
- '''Run experiments with the specified setup with the use of EMA Workbench and save the results.
-
- Args:
- experimental_setup (dict): A dictionary containing the setup for the experiments.
-
- Returns:
- None
- '''
- country = experimental_setup['country']
- return_period = experimental_setup['return_period']
- model = experimental_setup['model']
- n_scenarios = experimental_setup['n_scenarios']
- n_policies = experimental_setup['n_policies']
- multiprocessing = experimental_setup['multiprocessing']
- n_processes = experimental_setup['n_processes']
-
- if multiprocessing:
- with MultiprocessingEvaluator(model, n_processes=n_processes) as evaluator:
- results = evaluator.perform_experiments(
- scenarios=n_scenarios, policies=n_policies)
- else:
- results = perform_experiments(
- models=model, scenarios=n_scenarios, policies=n_policies)
-
- save_experiment_results(country, return_period, model,
- results, n_scenarios, n_policies)
-
-
-def save_experiment_results(country: str, return_period: int, model: Model, results: dict, n_scenarios: int, n_policies: int):
- """Saves experiment results to a file, taking into account if there was a conflict."""
- results_path = Path(f'../results/{country}')
- results_path.mkdir(parents=True, exist_ok=True)
-
- is_conflict = getattr(model.constants._data.get(
- 'is_conflict'), 'value', False)
-
- conflict_str = ", conflict=True" if is_conflict else ""
- filename = f"return_period={return_period}, scenarios={n_scenarios}, policies={n_policies}{conflict_str}.tar.gz"
- save_results(results, results_path / filename)
diff --git a/experiments/model_setup.py b/experiments/model_setup.py
deleted file mode 100644
index 67b1f3c..0000000
--- a/experiments/model_setup.py
+++ /dev/null
@@ -1,48 +0,0 @@
-from ema_workbench import Model
-from ema_workbench.em_framework.parameters import IntegerParameter, CategoricalParameter, Constant
-from ema_workbench.em_framework.outcomes import ArrayOutcome
-from unbreakable.model import model
-
-
-def setup_model(config: dict) -> Model:
- """
- Set up the EMA Workbench model based on the provided configuration.
-
- Args:
- config (dict): Configuration dictionary loaded from the YAML file.
-
- Returns:
- Model: Configured EMA Workbench model.
- """
- my_model = Model(name="model", function=model)
-
- # Extract and set up uncertainties, constants, and levers from the config
- # uncertainties = config.get("uncertainties", {})
- constants = config.get("constants", {})
- levers = config.get("levers", {})
-
- # Define seed as an uncertainty for multiple runs,
- # By specifying a wider range, we want to ensure that the seed is likely to be different for each run
- seed_start = 0
- seed_end = 1000000000
-
- # Fix seed to ensure reproducibility
- # NOTE: If running multiple instances of the model in parallel, the seed will be the same for all instances
- # np.random.seed(42)
-
- my_model.uncertainties = [IntegerParameter(
- "random_seed", seed_start, seed_end)]
-
- # Constants
- my_model.constants = [Constant(key, value)
- for key, value in constants.items()]
-
- # Levers
- my_model.levers = [CategoricalParameter(
- 'current_policy', [values for _, values in levers.items()])]
-
- # Outcomes
- my_model.outcomes = [ArrayOutcome(region)
- for region in constants.get('regions', [])]
-
- return my_model
diff --git a/main.py b/main.py
deleted file mode 100644
index 82ce3e6..0000000
--- a/main.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from experiments.config_manager import load_config
-from experiments.model_setup import setup_model
-from experiments.experiment_runner import run_experiments
-from ema_workbench import ema_logging
-
-ema_logging.log_to_stderr(ema_logging.INFO)
-
-
-def main():
- try:
- country = 'Dominica'
- disaster_type = 'hurricane'
- return_period = 100
- is_conflict = False
- config = load_config(country, return_period,
- disaster_type, is_conflict)
- model = setup_model(config)
-
- experimental_setup = {
- 'country': country,
- 'return_period': return_period,
- 'model': model,
- 'n_scenarios': 2,
- 'n_policies': 0,
- 'multiprocessing': False,
- 'n_processes': 12
- }
-
- run_experiments(experimental_setup)
-
- except Exception as e:
- print(f"An error occurred: {e}")
-
-
-if __name__ == "__main__":
- main()
diff --git a/requirements.txt b/requirements.txt
index 309e08c..f82c3d8 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,14 +1,291 @@
-ema_workbench==2.4.1
-geopandas==0.12.2
-mapclassify==2.5.0
-matplotlib==3.7.1
-mycolorpy==1.5.1
-numpy==1.24.3
-pandas==1.5.3
-ptitprince==0.2.6
-PyYAML==6.0
-scikit_learn==1.2.2
-scipy==1.10.1
-seaborn==0.11.0
-setuptools==68.0.0
-tqdm==4.65.0
+# This file may be used to create an environment using:
+# $ conda create --name --file
+# platform: win-64
+anyio=4.4.0=pyhd8ed1ab_0
+argon2-cffi=23.1.0=pyhd8ed1ab_0
+argon2-cffi-bindings=21.2.0=py311he736701_5
+arrow=1.3.0=pyhd8ed1ab_0
+asttokens=2.4.1=pyhd8ed1ab_0
+astunparse=1.6.3=py_0
+async-lru=2.0.4=pyhd8ed1ab_0
+attrs=23.1.0=py311haa95532_0
+babel=2.14.0=pyhd8ed1ab_0
+beautifulsoup4=4.12.3=pyha770c72_0
+blas=1.0=mkl
+bleach=6.1.0=pyhd8ed1ab_0
+blosc=1.21.3=h6c2663c_0
+boost-cpp=1.82.0=h59b6b97_2
+bottleneck=1.3.7=py311hd7041d2_0
+branca=0.6.0=py311haa95532_0
+brotli=1.0.9=h2bbff1b_8
+brotli-bin=1.0.9=h2bbff1b_8
+brotli-python=1.0.9=py311hd77b12b_8
+bzip2=1.0.8=h2bbff1b_6
+ca-certificates=2024.8.30=h56e8100_0
+cachecontrol=0.12.11=py311haa95532_1
+cached-property=1.5.2=hd8ed1ab_1
+cached_property=1.5.2=pyha770c72_1
+cairo=1.16.0=haedb8bc_5
+certifi=2024.8.30=py311haa95532_0
+cffi=1.16.0=py311h2bbff1b_1
+cfitsio=3.470=h2bbff1b_7
+charset-normalizer=3.3.2=pyhd3eb1b0_0
+cleo=2.1.0=py311haa95532_0
+click=8.1.7=py311haa95532_0
+click-plugins=1.1.1=pyhd3eb1b0_0
+cligj=0.7.2=pyhd3eb1b0_0
+colorama=0.4.6=py311haa95532_0
+comm=0.2.2=pyhd8ed1ab_0
+contourpy=1.2.0=py311h59b6b97_0
+crashtest=0.4.1=py311haa95532_0
+cryptography=43.0.0=py311h89fc84f_0
+cycler=0.11.0=pyhd3eb1b0_0
+debugpy=1.8.5=py311hda3d55a_1
+decorator=5.1.1=pyhd8ed1ab_0
+defusedxml=0.7.1=pyhd8ed1ab_0
+dill=0.3.8=pypi_0
+distlib=0.3.8=py311haa95532_0
+dulwich=0.21.3=py311h2bbff1b_0
+ema-workbench=2.5.2=pypi_0
+entrypoints=0.4=pyhd8ed1ab_0
+et_xmlfile=1.1.0=py311haa95532_0
+exceptiongroup=1.2.2=pyhd8ed1ab_0
+executing=2.1.0=pyhd8ed1ab_0
+expat=2.6.3=h5da7b33_0
+filelock=3.13.1=py311haa95532_0
+fiona=1.9.5=py311hf62ec03_0
+folium=0.14.0=py311haa95532_0
+fontconfig=2.14.1=hb33846d_3
+fonttools=4.51.0=py311h2bbff1b_0
+fqdn=1.5.1=pyhd8ed1ab_0
+freetype=2.12.1=ha860e81_0
+freexl=2.0.0=hd7a5696_0
+gdal=3.6.2=py311h4e7b5b2_5
+geopandas=0.14.2=py311haa95532_0
+geopandas-base=0.14.2=py311haa95532_0
+geos=3.8.0=h33f27b4_0
+geotiff=1.7.0=h4545760_3
+glib=2.78.4=hd77b12b_0
+glib-tools=2.78.4=hd77b12b_0
+h11=0.14.0=pyhd8ed1ab_0
+h2=4.1.0=pyhd8ed1ab_0
+hdf4=4.2.13=h712560f_2
+hdf5=1.12.1=h51c971a_3
+hpack=4.0.0=pyh9f0ad1d_0
+html5lib=1.1=pyhd3eb1b0_0
+httpcore=1.0.5=pyhd8ed1ab_0
+httpx=0.27.2=pyhd8ed1ab_0
+hyperframe=6.0.1=pyhd8ed1ab_0
+icc_rt=2022.1.0=h6049295_2
+icu=73.1=h6c2663c_0
+idna=3.7=py311haa95532_0
+importlib-metadata=7.0.1=py311haa95532_0
+importlib_metadata=7.0.1=hd3eb1b0_0
+importlib_resources=6.4.5=pyhd8ed1ab_0
+intel-openmp=2023.1.0=h59b6b97_46320
+ipykernel=6.29.5=pyh4bbf305_0
+ipyparallel=8.6.1=py311haa95532_0
+ipython=8.27.0=pyh7428d3b_0
+isoduration=20.11.0=pyhd8ed1ab_0
+jaraco.classes=3.2.1=pyhd3eb1b0_0
+jedi=0.19.1=pyhd8ed1ab_0
+jinja2=3.1.4=py311haa95532_0
+joblib=1.4.2=py311haa95532_0
+jpeg=9e=h827c3e9_3
+json5=0.9.25=pyhd8ed1ab_0
+jsonpointer=3.0.0=py311h1ea47a8_1
+jsonschema=4.19.2=py311haa95532_0
+jsonschema-specifications=2023.7.1=py311haa95532_0
+jsonschema-with-format-nongpl=4.19.2=pyhd8ed1ab_0
+jupyter-lsp=2.2.5=pyhd8ed1ab_0
+jupyter_client=7.4.9=pyhd8ed1ab_0
+jupyter_core=5.7.2=py311h1ea47a8_0
+jupyter_events=0.10.0=pyhd8ed1ab_0
+jupyter_server=2.14.2=pyhd8ed1ab_0
+jupyter_server_terminals=0.5.3=pyhd8ed1ab_0
+jupyterlab=4.2.5=pyhd8ed1ab_0
+jupyterlab_pygments=0.3.0=pyhd8ed1ab_1
+jupyterlab_server=2.27.3=pyhd8ed1ab_0
+kealib=1.5.0=hde4a422_1
+keyring=23.13.1=py311haa95532_0
+kiwisolver=1.4.4=py311hd77b12b_0
+krb5=1.20.1=h5b6d351_0
+lcms2=2.12=h83e58a3_0
+lerc=3.0=hd77b12b_0
+libboost=1.82.0=h3399ecb_2
+libbrotlicommon=1.0.9=h2bbff1b_8
+libbrotlidec=1.0.9=h2bbff1b_8
+libbrotlienc=1.0.9=h2bbff1b_8
+libclang=14.0.6=default_hb5a9fac_1
+libclang13=14.0.6=default_h8e68704_1
+libcurl=8.9.1=h0416ee5_0
+libdeflate=1.17=h2bbff1b_1
+libffi=3.4.4=hd77b12b_1
+libgdal=3.6.2=h0e70117_5
+libglib=2.78.4=ha17d25a_0
+libiconv=1.16=h2bbff1b_3
+libkml=1.3.0=h63940dd_7
+libnetcdf=4.8.1=h6685c40_4
+libpng=1.6.39=h8cc25b3_0
+libpq=12.17=h906ac69_0
+libsodium=1.0.18=h8d14728_1
+libspatialindex=1.9.3=h6c2663c_0
+libspatialite=5.1.0=h25d3e1c_1
+libssh2=1.11.0=h291bd65_0
+libtiff=4.5.1=hd77b12b_0
+libwebp-base=1.3.2=h2bbff1b_0
+libxml2=2.13.1=h24da03e_2
+libzip=1.8.0=h289538f_1
+llvmlite=0.43.0=py311hf2fb9eb_0
+lockfile=0.12.2=py311haa95532_0
+lz4-c=1.9.4=h2bbff1b_1
+mapclassify=2.5.0=py311haa95532_0
+markupsafe=2.1.3=py311h2bbff1b_0
+matplotlib=3.9.2=py311haa95532_0
+matplotlib-base=3.9.2=py311h472561b_0
+matplotlib-inline=0.1.7=pyhd8ed1ab_0
+minizip=4.0.3=hb68bac4_0
+mistune=3.0.2=pyhd8ed1ab_0
+mkl=2023.1.0=h6b88ed4_46358
+mkl-service=2.4.0=py311h2bbff1b_1
+mkl_fft=1.3.10=py311h827c3e9_0
+mkl_random=1.2.7=py311hea22821_0
+more-itertools=10.1.0=py311haa95532_0
+msgpack-python=1.0.3=py311h59b6b97_0
+multiprocess=0.70.16=pypi_0
+nbclient=0.10.0=pyhd8ed1ab_0
+nbconvert=7.16.4=hd8ed1ab_1
+nbconvert-core=7.16.4=pyhd8ed1ab_1
+nbconvert-pandoc=7.16.4=hd8ed1ab_1
+nbformat=5.10.4=pyhd8ed1ab_0
+nest-asyncio=1.6.0=pyhd8ed1ab_0
+networkx=3.3=py311haa95532_0
+notebook=7.2.2=pyhd8ed1ab_0
+notebook-shim=0.2.4=pyhd8ed1ab_0
+numba=0.60.0=py311hea22821_0
+numexpr=2.8.7=py311h1fcbade_0
+numpy=1.26.4=py311hdab7c0b_0
+numpy-base=1.26.4=py311hd01c5d8_0
+openjpeg=2.5.2=hae555c5_0
+openpyxl=3.1.5=py311h827c3e9_0
+openssl=3.3.2=h2466b09_0
+overrides=7.7.0=pyhd8ed1ab_0
+packaging=24.1=py311haa95532_0
+pandas=2.2.2=py311hea22821_0
+pandoc=2.12=haa95532_3
+pandocfilters=1.5.0=pyhd8ed1ab_0
+parso=0.8.4=pyhd8ed1ab_0
+patsy=0.5.6=pypi_0
+pcre2=10.42=h0ff8eda_1
+pdoc=14.4.0=pyhd8ed1ab_0
+pexpect=4.8.0=pyhd3eb1b0_3
+pickleshare=0.7.5=py_1003
+pillow=10.4.0=py311h827c3e9_0
+pip=24.2=py311haa95532_0
+pixman=0.40.0=h2bbff1b_1
+pkginfo=1.10.0=py311haa95532_0
+platformdirs=2.5.2=py311haa95532_0
+platypus-opt=1.3.1=pypi_0
+ply=3.11=py311haa95532_0
+poetry=1.4.0=py311haa95532_0
+poetry-core=1.5.1=py311haa95532_0
+poetry-plugin-export=1.3.0=py311hfacae44_0
+poppler=22.12.0=h0bf3bde_3
+poppler-data=0.4.11=haa95532_1
+proj=9.3.1=ha107b6e_0
+prometheus_client=0.20.0=pyhd8ed1ab_0
+prompt-toolkit=3.0.47=pyha770c72_0
+psutil=6.0.0=py311he736701_1
+ptyprocess=0.7.0=pyhd3eb1b0_2
+pure_eval=0.2.3=pyhd8ed1ab_0
+pybind11-abi=5=hd3eb1b0_0
+pycparser=2.21=pyhd3eb1b0_0
+pygments=2.18.0=pyhd8ed1ab_0
+pyopenssl=24.2.1=py311haa95532_0
+pyparsing=3.1.2=py311haa95532_0
+pyproj=3.6.1=py311ha997c60_0
+pyproject_hooks=1.0.0=py311haa95532_0
+pyqt=5.15.10=py311hd77b12b_0
+pyqt5-sip=12.13.0=py311h2bbff1b_0
+pysocks=1.7.1=py311haa95532_0
+python=3.11.9=he1021f5_0
+python-build=0.10.0=py311haa95532_0
+python-dateutil=2.9.0post0=py311haa95532_2
+python-fastjsonschema=2.20.0=pyhd8ed1ab_0
+python-installer=0.6.0=py311haa95532_0
+python-json-logger=2.0.7=pyhd8ed1ab_0
+python-tzdata=2023.3=pyhd3eb1b0_0
+python_abi=3.11=2_cp311
+pytz=2024.1=py311haa95532_0
+pywin32=306=py311h12c1d0e_2
+pywin32-ctypes=0.2.2=py311haa95532_0
+pywinpty=2.0.13=py311hda3d55a_1
+pyyaml=6.0.2=py311he736701_1
+pyzmq=24.0.1=py311h7b3f143_1
+qhull=2020.2=h59b6b97_2
+qt-main=5.15.2=h19c9488_10
+rapidfuzz=3.5.2=py311h5da7b33_0
+referencing=0.30.2=py311haa95532_0
+requests=2.32.3=py311haa95532_0
+requests-toolbelt=0.9.1=pyhd3eb1b0_0
+rfc3339-validator=0.1.4=pyhd8ed1ab_0
+rfc3986-validator=0.1.1=pyh9f0ad1d_0
+rpds-py=0.10.6=py311h062c2fa_0
+rtree=1.0.1=py311h2eaa2aa_0
+salib=1.5.1=pypi_0
+scikit-learn=1.5.1=py311hea22821_0
+scipy=1.13.1=py311h9f229c6_0
+seaborn=0.13.2=py311haa95532_0
+send2trash=1.8.3=pyh5737063_0
+setuptools=72.1.0=py311haa95532_0
+shapely=2.0.5=py311h82fc408_0
+shellingham=1.5.0=py311haa95532_0
+sip=6.7.12=py311hd77b12b_0
+six=1.16.0=pyhd3eb1b0_1
+sniffio=1.3.1=pyhd8ed1ab_0
+soupsieve=2.5=pyhd8ed1ab_1
+sqlite=3.45.3=h2bbff1b_0
+stack_data=0.6.2=pyhd8ed1ab_0
+statsmodels=0.14.2=pypi_0
+tbb=2021.8.0=h59b6b97_0
+terminado=0.18.1=pyh5737063_0
+threadpoolctl=3.5.0=py311h746a85d_0
+tiledb=2.3.3=hd8964de_3
+tinycss2=1.3.0=pyhd8ed1ab_0
+tk=8.6.14=h0416ee5_0
+tomli=2.0.1=pyhd8ed1ab_0
+tomlkit=0.11.1=py311haa95532_0
+tornado=6.4.1=py311h827c3e9_0
+tqdm=4.66.5=py311h746a85d_0
+traitlets=5.14.3=pyhd8ed1ab_0
+trove-classifiers=2023.10.18=py311haa95532_0
+types-python-dateutil=2.9.0.20240906=pyhd8ed1ab_0
+typing-extensions=4.12.2=hd8ed1ab_0
+typing_extensions=4.12.2=pyha770c72_0
+typing_utils=0.1.0=pyhd8ed1ab_0
+tzdata=2024a=h04d1e81_0
+ucrt=10.0.22621.0=h57928b3_0
+unbreakable=0.3.0=dev_0
+unicodedata2=15.1.0=py311h2bbff1b_0
+uri-template=1.3.0=pyhd8ed1ab_0
+uriparser=0.9.7=h2bbff1b_0
+urllib3=1.26.19=py311haa95532_0
+vc=14.40=h2eaa2aa_0
+vc14_runtime=14.40.33810=hcc2c482_20
+virtualenv=20.16.2=py311haa95532_0
+vs2015_runtime=14.40.33810=h3bf8584_20
+wcwidth=0.2.13=pyhd8ed1ab_0
+webcolors=24.8.0=pyhd8ed1ab_0
+webencodings=0.5.1=py311haa95532_1
+websocket-client=1.8.0=pyhd8ed1ab_0
+wheel=0.43.0=py311haa95532_0
+win_inet_pton=1.1.0=py311haa95532_0
+winpty=0.4.3=4
+xerces-c=3.2.4=hd77b12b_1
+xyzservices=2022.9.0=py311haa95532_1
+xz=5.4.6=h8cc25b3_1
+yaml=0.2.5=h8ffe710_2
+zeromq=4.3.4=h0e60522_1
+zipp=3.17.0=py311haa95532_0
+zlib=1.2.13=h8cc25b3_1
+zstd=1.5.5=hd43e919_2
\ No newline at end of file
diff --git a/sensitivity-analysis.ipynb b/sensitivity-analysis.ipynb
deleted file mode 100644
index 2c95c12..0000000
--- a/sensitivity-analysis.ipynb
+++ /dev/null
@@ -1,362 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [],
- "source": [
- "import pandas as pd\n",
- "import numpy as np\n",
- "import matplotlib.pyplot as plt\n",
- "import math\n",
- "import numpy as np\n",
- "import seaborn as sns\n",
- "import scipy.stats as stats"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [],
- "source": [
- "def generate_households(num_households=1, exp:float = None, v:float = None, fix_seed:bool=True):\n",
- " '''Generate dummy households.'''\n",
- " if fix_seed:\n",
- " np.random.seed(0) # Ensure reproducibility\n",
- "\n",
- " data = {'exp_house': 0,\n",
- " 'consumption_loss': 0,\n",
- " 'consumption_loss_npv': 0,\n",
- " 'net_consumption_loss': 0,\n",
- " 'net_consumption_loss_npv': 0,\n",
- " 'c_t': 0,\n",
- " 'c_t_unaffected': 0,\n",
- " 'wellbeing': 0}\n",
- " \n",
- " if exp is None:\n",
- " # Generate expenditure\n",
- " lower, upper = 153, 5474\n",
- " mu, sigma = 1099, 1099\n",
- " X = stats.truncnorm((lower - mu) / sigma,\n",
- " (upper - mu) / sigma, loc=mu, scale=sigma)\n",
- " exp = X.rvs(num_households)\n",
- " data['exp'] = exp\n",
- " else:\n",
- " data['exp'] = exp\n",
- "\n",
- " # Income is a product of expenditure and a random coefficient\n",
- " inc_multiplier = 1.48 \n",
- " inc_delta = 0.1\n",
- " low = inc_multiplier - inc_delta\n",
- " high = inc_multiplier + inc_delta\n",
- " data['inc'] = data['exp'] * np.random.uniform(low, high)\n",
- "\n",
- " sav_multiplier = 0.0204\n",
- " sav_delta = 0.02\n",
- " low = sav_multiplier - sav_delta\n",
- " high = sav_multiplier + sav_delta\n",
- " data['sav'] = data['inc'] * np.random.uniform(low, high)\n",
- "\n",
- " # divide by average productivity of capital\n",
- " data['keff'] = data['inc'] / 0.35\n",
- "\n",
- " if v is None:\n",
- " data['v'] = np.random.uniform(0.2, 0.8, num_households)\n",
- " else:\n",
- " data['v'] = v\n",
- "\n",
- " # Sort column)\n",
- " sorted_columns = ['exp', 'inc', 'sav', 'keff', 'exp_house', 'v', 'consumption_loss', 'consumption_loss_npv',\n",
- " 'net_consumption_loss', 'net_consumption_loss_npv', 'c_t', 'c_t_unaffected', 'wellbeing']\n",
- "\n",
- " return pd.DataFrame(data, index=[0])[sorted_columns]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [],
- "source": [
- "def calculate_consumption_recovery(df:pd.DataFrame, parameters:dict, print_statistics:bool=False) -> pd.DataFrame:\n",
- " '''Calculate consumption recovery'''\n",
- " initial_expenditure = df['exp'].values\n",
- " initial_savings = df['sav'].values\n",
- " effective_capital = df['keff'].values\n",
- "\n",
- " recovery_rate = parameters['recovery_rate']\n",
- " years_to_recover = parameters['years_to_recover']\n",
- " income_and_expenditure_growth = parameters['income_and_expenditure_growth']\n",
- " average_productivity = parameters['average_productivity']\n",
- " consumption_utility = parameters['consumption_utility']\n",
- " discount_rate = parameters['discount_rate']\n",
- " \n",
- " try:\n",
- " vulnerability_increase_factor = parameters['vulnerability_increase_factor']\n",
- " vulnerability = parameters['v']\n",
- " except:\n",
- " vulnerability_increase_factor = 1\n",
- " vulnerability = df['v'].values\n",
- " \n",
- " totaL_weeks = 52 * years_to_recover\n",
- " dt = 1 / 52\n",
- " consumption = {}\n",
- " consumption_unaffected = {}\n",
- " wellbeing = {}\n",
- " consumption_loss = {}\n",
- " consumption_loss_npv = {}\n",
- "\n",
- " for time in np.linspace(0, years_to_recover, totaL_weeks):\n",
- " exponential_multiplier = np.e**(-recovery_rate * time)\n",
- " growth_factor = (1 + income_and_expenditure_growth)**time\n",
- "\n",
- " current_expenditure = growth_factor * initial_expenditure\n",
- " current_savings = growth_factor * initial_savings * (1 / vulnerability_increase_factor) # * recovery_rate\n",
- " \n",
- " asset_loss = growth_factor * effective_capital * vulnerability * vulnerability_increase_factor * recovery_rate \n",
- " income_loss = growth_factor * average_productivity * effective_capital * vulnerability * vulnerability_increase_factor # * recovery_rate\n",
- " # income_loss = 0\n",
- "\n",
- " c_t = np.maximum(current_expenditure + exponential_multiplier * (current_savings - asset_loss - income_loss), 0)\n",
- " c_t_unaffected = current_expenditure\n",
- " c_t = np.minimum(c_t, c_t_unaffected)\n",
- " \n",
- " consumption[time] = c_t\n",
- " consumption_unaffected[time] = c_t_unaffected\n",
- " consumption_loss[time] = dt * (c_t_unaffected - c_t)\n",
- " consumption_loss_npv[time] = dt * (c_t_unaffected - c_t)*np.e**(-discount_rate * time)\n",
- "\n",
- " wellbeing[time] = c_t_unaffected**(1 - consumption_utility) / (1 - consumption_utility) * dt \\\n",
- " * ((1 - ((c_t_unaffected - c_t) / c_t_unaffected) * np.e**(-recovery_rate * time))**(1 - consumption_utility) - 1) \\\n",
- " * np.e**(-discount_rate * time)\n",
- "\n",
- " total_consumption_loss = sum(consumption_loss.values())\n",
- " total_consumption_loss_npv = sum(consumption_loss_npv.values())\n",
- "\n",
- " if print_statistics:\n",
- " print('Total consumption loss:', \"{:,}\".format(round(total_consumption_loss[0])))\n",
- " print('Total consumption loss NPV:', \"{:,}\".format(round(total_consumption_loss_npv[0])))\n",
- "\n",
- " return pd.DataFrame(consumption), pd.DataFrame(consumption_unaffected), pd.DataFrame(consumption_loss), pd.DataFrame(consumption_loss_npv), pd.DataFrame(wellbeing)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Total consumption loss: 10,221\n",
- "Total consumption loss NPV: 9,464\n"
- ]
- },
- {
- "data": {
- "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAEECAYAAAA4Qc+SAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAArEAAAKxAFmbYLUAAAoQklEQVR4nO3deViU9cI38O9s7MMqI8sAIuAyyCKK4pqabSg8B48tetRjJ+p4skyLY8spj8fnPfmcltPr++ipDM20IjNTg1ZLyxV3RUQSFYhFGUR2GJjlfv/AKFMcVGbuYeb7ua65YG5m+Y7X5Zcfv3v5SQRBEEBERL2eVOwARETUM1joRER2goVORGQnWOhERHaChU5EZCdY6EREdsLmCz0lJUXsCEREvYLNF3p1dbXYEYiIegWbL3QiIuoeFjoRkZ1goRMR2QkWOhGRnWChExHZCRY6EZGdsMtCFwQBBZUNuFDfKnYUIiKrsctCb2oz4Her9iLrYJnYUYiIrMYuC13posCYSD98nX9R7ChERFZjl4UOAPcOCcCPVY04X90kdhQiIquw20K/SxMAqQT46hRH6UTkGOy20H3dnTAynNMuROQ47LbQAeC+mACcKK9HRR2PdiEi+2fXhX63JgAAOEonIodg14Ue4OWCoaHe+IqFTkQOwK4LHQDuGxKAQ6WXUd3YJnYUIiKLsvtCvzc6EIIAfFPAUToR2Te7L/RQPzdoAj057UJEds/uCx3oOMlo/7ka1LfoxY5CRGQxDlPoBpOA7aerxI5CRGQxDlHoUSoPRKo88HlepdhRiIgsxiEKXSKRICU2CLuLLqG2uV3sOEREFuEQhQ4AU+MCYTAJvLYLEdkthyn0CH8PRAd5IvsEp12IyD45TKEDQEpcEPafr4G2QSd2FCKiHudQhT4lpuMkoy9OXhA7ChFRj3OoQg/xdUNCqDey81joRGR/HKrQgY5plyOltSivbRE7ChFRj3K4Qp8SEwiJBPico3QisjMOV+gqTxckhfshh4VORHbG4Qod6Jh2OVlRj+JLzWJHISLqMQ5Z6PcNCYBcKsG24xViRyEi6jEOWeg+7k6YMNAfW45VQBAEseMQEfUIhyx0AJiWoEZpTQuO/lQndhQioh7hsIU+aZAKni5yfHq0XOwoREQ9wqKF/sYbbyA6OhoajQYLFiyAIAg4ePAgoqOjERkZiWXLllny7W/IRSHD1LggZJ+oRJvBKFoOIqKeYrFCr66uxsqVK3HkyBGcPHkSR44cQW5uLubPn4+srCwUFhYiOzsb+fn5lopg1rShwWjQGbDjtFa0DEREPcWiI3SDwQCdTge9Xg+9Xg+TyQSDwYDY2FjI5XLMnDkT2dnZloxwQ8PCfBDq64bNR3m0CxH1fhYrdH9/f2RkZCA0NBRBQUGYPHkynJ2dERwc3PkYtVqNigrxylQikWBaQjC+/1GLmqY20XIQEfUEixV6bW0tcnJyUFJSgoqKCuzbtw/NzdeeyCORSK7ZlpmZiaSkJCQlJUGrtex0yLShahhMAs8cJaJez2KF/u233yIyMhK+vr5wdXXFlClT8MMPP1w1Ii8vL0dgYOA1z01PT0dubi5yc3OhUqksFREAEOrnhsR+PjzahYh6PYsVekhICPbt2wedTgej0Yjvv/8ecXFxkMlkyMvLg8FgQFZWFlJSUiwVodumJahxorweZ7WNYkchIrplFiv0pKQkJCcnY+jQoYiNjUVERARSU1OxcuVKzJgxAwMHDkRycjJiYmIsFaHbkmMC4SSXYtMRjtKJqPeSCDZ+7ntSUhJyc3Mt/j4LPzqGPWdrsP/5SVDIHPZ8KyLqxdhcVzyYGIpLTW3YUchj0omod2KhX5HU3xf9/Nyw8VCZ2FGIiG4JC/0KiUSCBxJD8P2PWlyobxU7DhHRTWOh/8r0BDUkEgk2HebOUSLqfVjov6LydMGkQSpsPFQGk8mm9xUTEV2Dhf4bDyWGoKKuFXvPXRI7ChHRTWGh/8YdA/zR19MZH3HnKBH1Miz035DLpLh/WAi+OXURl5vbxY5DRNRtLPTreGB4CPRGAZt55igR9SIs9OsI9XPD+AH+eP9AKXeOElGvwULvwpykMJTWtGBXUbXYUYiIuoWF3oWJg1QI9nbFhv2lYkchIuoWFnoXZFIJZiWFYcePWpRdbhE7DhGRWSz0G3gwMQQKmRQfHPhJ7ChERGax0G/A190JU2MDsfHQT9DpjWLHISK6IRa6GbOTwlDbosfnXHOUiGwcC92M+BBvxAR7YX0ud44SkW1joZshkUgwe1QYTpTVIa+8Tuw4RERdYqF3Q2pcEHzcFFi3t0TsKEREXbqpQm9ra0NlZaWlstgsF4UMs5LC8NmJSlys14kdh4jouswWelpaGhobG1FfX4/BgwfjzjvvxJIlS6yRzabMHhUGqUSC9ftLxI5CRHRdZgu9pKQESqUSn3zyCWbMmIGCggJs3brVCtFsi0rpgpS4IHxw4Ce0tBvEjkNEdA2zhd7W1oZz587hww8/RGpqKiQSiTVy2aRHxoajvlXPqzASkU0yW+hLlixBWloaBg4ciJEjR+L8+fOIjIy0RjabownyxJhIP6zZU8yrMBKRzZEIgnBTzSQIglVH6UlJScjNzbXa+5mzs1CLh9cdwjtzhuMuTV+x4xARdTI7Qp8/fz4aGxvR2tqKxMRE9O3bF2+99ZY1stmkOwb4I8LfHZm7z4sdhYjoKmYLfe/evVAqldi6dStGjhyJsrIyvPnmm9bIZpOkUgkeGdsfB4ov42R5vdhxiIg6mS10nU6H1tZWbNq0Cb///e/h7OxsjVw2bVpCMPzcnfDWrnNiRyEi6mS20OfNmwe1Wg2dTocJEyagtLQUSqXSGtlslotChj+NDccXJy/gfHWT2HGIiADcwk5RADAYDJDL5ZbIcw1b2yn6s/pWPcb8zw4kxwTglelxYschIjI/Qq+rq8PChQsxbNgwDB8+HIsWLUJTE0elXq4KzB4Vhi3HKlBZ1yp2HCIi84U+d+5cBAUFIScnB5999hmCg4Pxxz/+0RrZbN6fxoRDKpHgHR7xQkQ2oFun/i9evBiBgYEICgpCRkYGSku7d23w4uJiTJw4ERqNBjExMWhubsbBgwcRHR2NyMhILFu27LY/gJj8lc54MDEEWQd/Qk1Tm9hxiMjBmS10Hx8fbN68ufP+p59+Cm9v7269+Ny5c7Fs2TIUFBTghx9+gLOzM+bPn4+srCwUFhYiOzsb+fn5txzeFjw2vj8MRgHr9pWIHYWIHJzZQl+7di3WrVuHgIAABAUFYd26dXj33XfNvvCpU6egUCgwbtw4AICvry+0Wi0MBgNiY2Mhl8sxc+ZMZGdn3/6nEJHaxw2p8UFYt68EjTq92HGIyIGZPVQlPDz8lkq3qKgIHh4eSE1NRXl5OaZPn467774bwcHBnY9Rq9X44Ycfbvq1bc3jEyKw5VgF1u8vxfyJjnmdGyISX5eF/te//vWG12x55ZVXbvjCer0eu3fvxvHjx6FSqXDvvfdCoVBc87jrvUdmZiYyMzMBAFqt9obvYwsiVUpMiQnEO7vPY86oMChdrv2cRESW1mWhDxky5LZeWK1WIzExESEhIQCA5ORktLS0oKKiovMx5eXlCAwMvOa56enpSE9PB9BxHHpvsHByFD4/eQHr9pbgyTujxI5DRA6oy0K/3UMTExMTUVVVhdraWnh5eWHXrl3485//jOzsbOTl5UGj0SArKwtr1qy5rfexFZEqJVLjgjpG6aP7wcuVo3Qisi6LLRItl8vx8ssvY/z48YiNjUVUVBSmTp2KlStXYsaMGRg4cCCSk5MRExNjqQhWt+DOKDS1GbB2T7HYUYjIAd3Sqf/WZKun/nfl6Y+PY/upKux+diK83ZzEjkNEDsRiI3RHtWBSFFr0RmTu5iidiKzL7GGLp0+fxuuvv47S0lIYjcbO7Tt27LBosN6qXx93TBsajHf3FuNPY8Ph685ROhFZh9lCf/DBB7Fo0SIsWLAAMpnMGpl6vScnRWHLsQq8+f1Z/G2KRuw4ROQgzBa6i4sLHn74YWtksRuhfm6YOTIU7+0vxdwx4Qj2dhU7EhE5ALNz6JMmTcLSpUtx7NgxFBQUdN7oxp6cFAWFVIJ/f3NG7ChE5CDMjtAPHDgAAFedoi+RSDiHboa/0hmPju+PFd8V4dHx4RgU4Cl2JCKyczxs0YKa2gyY8OpOxKq9sXZuothxiMjO3dKKRXV1dVaI1vt5OMvx1J1R2FGoRe75GrHjEJGd44pFFvbQiFD083PD8i8LYeN/DBFRL2fRFYsIUMikyLhnIE6U1eGLkxfFjkNEdsyiKxZRhykxgRga6o3lX56GTm80/wQioltgsRWL6BcSiQR/T4lGeW0rMrmgNBFZiMVWLKKrxYd4Y1pCMFbtPIfpw0IQ4OUidiQisjNdFvqKFSvw1FNPdblykbkVi+haz947CF/lX8QrXxXi3w/Gix2HiOxMl4Xev39/ALe/chH9oq+nC+ZPjMSrX/+IWaPCkBDqI3YkIrIjXRZ6SkpK5/e/PUzxvffes1wiO/fI2HBkHfwJ/8guwJa/jIZU2vW6rUREN8PsTtEVK1Z0axt1j4tChhenDMaJsjpsPloudhwisiNdjtA3bdqEjz/+GCUlJXjggQc6tzc0NMDHh1MFt+Oe6ACMjeyD5V8W4i5NX65sREQ9ostCHzFiBPz9/XHhwgXMnz+/c7tSqURsbKxVwtkriUSC//7dENzzf3fhX18VYvk0/nsS0e3rcsolLCwMEyZMwJ49ezBgwADU19ejoaEBgYGBkMvNHu1IZoT3ccfjEyKQdbAMR0ovix2HiOyA2Tn0t99+G+PGjcMXX3yBnJwc3HHHHVi9erU1stm9eXdEoJ+fG/62JR96o0nsOETUy5m9fO7gwYNx4MABeHp2XM+7oaEBI0aMQGFhoVUC9ubL53bH7qJqzF5zEH9LHoxHx/cXOw4R9WJmR+ghISGQSn95mFQqRXh4uEVDOZJxUf5IjQvCG9+eQUVdq9hxiKgXM1voSqUSQ4YMwbx58/CXv/wFMTEx8PPzw+LFi7F48WJrZLR7L04dDJlUghe3nOQldonolpndu5mamorU1NTO+0lJSRYN5IhUShe8NFWDxZ/kYcuxCkxLUIsdiYh6IS5BZyMEQcCctQeRV16P7U+Ph0rJi3cR0c0xO+Wybds2xMfHo2/fvlCpVPD394dKpbJGNocikUiwfFoMDEYTXtqaz6kXIrppZgv9mWeewcaNG1FVVQWtVovq6mpotVprZHM4ah83PHffIHx9qoqrGxHRTTNb6GFhYYiIiLBGFgLwh5FhGBHuiyXb8nG5uV3sOETUi5idQz969CgWLVqEsWPHwtnZuXP7kiVLLB4OcJw59F8rudSMe1fswsSBKvznDwnXvR49EdFvmR2hP/XUUxg4cCACAgLg5+fXeSPL6dfHHX+bosGX+Rex+WiF2HGIqJcwe9iiXq/nqf4imDUyFDtOV+Hv2/Ixop8vQv3cxI5ERDbO7Aj9rrvuwvr161FbW4uWlpbOG1mWRCLBv6bHwlkhw9MfH4fRxKNeiOjGzBb6+++/j7///e9ISEhAdHQ0oqOju70sXUtLC8LCwpCRkQEAOHjwIKKjoxEZGYlly5bdXnIHoFK64H+mxeBwaS3e+uGc2HGIyMaZnXIpLi6+5Rf/5z//iZEjR3benz9/PrKysqDRaDBq1ChMmzaNa5aacXd0AB5KDMEb289gbGQfxIV4ix2JiGyU2UJfv379dbfPmTPnhs8rKipCYWEhUlJSkJ+fj8rKShgMhs7FMWbOnIns7GwWeje8NFWDA8WX8UTWUeQ8OQ5ergqxIxGRDTI75XLy5MnO2+HDh7F8+XJ8/vnnZl84IyMDy5cv77xfWVmJ4ODgzvtqtRoVFTyCozvcneVYOXMoqhra8NzmPJ5FSkTXZXaE/uqrr151v6mpCQ899NANn7Nt2zYMGDAAAwYMwL59+wDguiXU1fHVmZmZyMzMBACelXpFdJAXlkzV4MWt+diQW4o5o/qJHYmIbMxNryUnkUhw5syZGz4mNzcXH330ETZt2oSmpibo9Xp4enpeNSIvLy9HYGDgdZ+fnp6O9PR0ALy646/9YWQo9p+vwf/JOY2EUB8MCfYSOxIR2RCzZ4omJiZ2jqSNRiMuXLiAxYsXY+HChd16g3Xr1iE/Px+vvfYahg8fjrVr10Kj0WD06NFYs2YNYmJibvh8RzxT9EYadXpM/d89AIDsJ8fC04Xz6UTUwewI/ZNPPvnlwXI5VCoVFIpbK5GVK1dixowZ0Ol0mD17ttkyp2spXRRYNTMB097ch4yPT+CtWcMglfLSAETUjRF6fn4+IiMj4eLigpycHOTl5SE9Pd1ql9DlCP36Pj5chsWf5OGZuwbgyTujxI5DRDbA7FEus2bNgpOTE/Lz8zuXnJsxY4bFg9GNPTA8BLOTwvDvb89gR2GV2HGIyAaYLXSJRAKpVIrNmzdj0aJFeOGFF1BbW2uNbGTGS1M1GBbqg6c+Oo7iS81ixyEikZktdHd3d7z00ktYv349pk6dCqPRCL1eb41sZIaTXIr/zEqAm5MMj60/jKY2g9iRiEhEZgt906ZN8PHxwbp16xAYGIiKigr89a9/tUY26gaV0gVvzhqG0poWPJV1jBfxInJgXCTaTmw5Vo5FG0/gT2PCsSRFI3YcIhKB2RH6xx9/jKioKKhUKi4SbcPShqqx4M4orN1bjA37S8SOQ0QiMHsc+gsvvIBvvvkG/fv3t0Yeug2LJkeh5FIzlmYXIMTXDRMG8hcvkSMxO0IPDg5GeHi4NbLQbZJIJHhleizi1F544sNjOH2hQexIRGRFZufQH330UZSUlCA5OfmqRaIff/xxi4cDOId+K2qa2pD2n33Q6Y3Y/JfRCPHl8nVEjsDsCF2tVmPs2LFoaGhAdXV1541sl5+HMzY8MgImAZi95gAuNbWJHYmIrKDbR7k0NjZCIpHAw8PD0pmuwhH6rTtVWY+H3s5FWB83ZD2aBCUv5EVk18yO0PPy8hAfH4/ExEQkJCQgISEBeXl51shGtyk6yAur5wzHmaom/HnDEbQZjGJHIiILMlvojz32GN5++20UFhbizJkzeOutt/DYY49ZIxv1gFERfvh/Dw1F7vkaLNp4HAajSexIRGQhZgu9paXlqoWeR4wYgdbWVouGop5175AAvJwWgy9OXsQzm07wbFIiO2X2OPT4+Hg88cQTmDVrFgDggw8+6FzomXqPh0aEQm804aVtpyCTSvDq9DjIeB11IrtittBXr16NVatW4V//+hcAYNy4cVY7ZJF61uxR/WAwCfhHdgHkUgn+Z1osF8cgsiNdHuVSX1+P2tpa9OvX76rtxcXF8PPzg6enpzXy8SgXC3hn13n884vTmDkyFP/83ZAuF+smot6lyzn0J554AmfPnr1m+6lTp/Dkk09aNBRZ1qPj+2PxvQPx4YGf8MKWk5xTJ7ITXRb6sWPHMHny5Gu2T506FUePHrVoKLK8xydE4rn7BiHrYBkWbTwOPY9+Ier1upxD1+l0XT6prY1nHtqDeXdEwN1Zjpe25qOl3YCVMxPgopCJHYuIblGXI/SYmBh88MEH12z/8MMPMXjwYIuGIuuZnRSGfz8Qh50/VuNP6w6hmaseEfVaXe4ULS8vR1paGjw9PREfHw+JRIKjR4+ioaEBW7duhVqttkpA7hS1jq/yL2JB1jFEB3tizR8T4evuJHYkIrpJZq/l8t1336GgoACCIECj0Vx3Xt2SWOjWs7uoGvM2HIHK0wXrHk5EmJ+72JGI6CZwCTq6Sn5FPR5edwgmk4A1cxMRH+ItdiQi6iazp/6TYxkS7IUtj4+Gj7sTHlq9H98WVIkdiYi6iYVO11D7uGHzvNGIU3vjsQ2HsW5vMWz8DzkiAguduuDlpsD6R0YgNS4IS7ML8PynJ9Fu4LHqRLbM7LVcyHE5y2V448F4DAr0xL++KsRZbRPenDUM/kpn808mIqvjCJ1uSCKRYN4dEVj7x0T8eLERqSv34GR5vdixiOg6WOjULRMHqbBl/hi4KmSY/tY+fHy4TOxIRPQbLHTqtkiVB7bMH4NxUf5Y/Ekenvn4BFraeWYpka1godNN8XJV4J05w/C35MHYerwCv1u1F2e1jWLHIiKw0OkWSCQSPDq+PzY+loSGVgNSV+7Fp0fLeWgjkcgsVuhlZWWYMGECNBoNYmNjsWnTJgDAwYMHER0djcjISCxbtsxSb09WMLyfLz5fMBaJ/Xzx9Mcn8GTWMdS36MWOReSwLHbq/4ULF1BVVYX4+HhotVokJCTgxx9/xIQJE7BmzRpoNBqMGjUK7777LoYMGdLl6/DUf9tnMglYv78Ey78shI+bE15/IA5jIvuIHYvI4VhshB4YGIj4+HgAgEqlgq+vLy5dugSDwYDY2FjI5XLMnDkT2dnZlopAViKVSjB3TDhynhwLX3cn/CHzAP47pwA6vVHsaEQOxSpz6IcPH4bJZEJ1dTWCg4M7t6vValRUVFzz+MzMTCQlJSEpKQlardYaEakHRPVVYuv8MfjLhAis3VuMlP/dgyOltWLHInIYFi/0mpoazJkzB6tXr77uTrPrLVCcnp6O3Nxc5ObmQqVSWToi9SAnuRTP3jsIGx8bBYNJwPS39mHpZ6e4cAaRFVi00Nva2pCWlobnn38eo0ePRnBw8FUj8vLycgQGBloyAolkRLgvvnxqHObdEYENuaW4+41d+P5H/rVFZEkWK3RBEDB37lxMmjQJs2fPBgAEBQVBJpMhLy8PBoMBWVlZSElJsVQEEpmLQoZn7x2EbfPHwMddgbnvHsLCj45B29j1erVEdOssdpTLnj17MH78eMTGxnZu27BhA5qbm/HII49Ap9Nh9uzZWLp06Q1fh0e52AeD0YTMPcVY8W0RZFIJFk6Owh9H94NCxlMhiHoKVywiq6qsa8U/vziNz/MuIFLlgX+kRvMQR6IewuERWVWQtytWzUzAh+kjIQHwh8wDePyDIyitaRY7GlGvxxE6iUZvNOG9fSVY8V0RdHojZiWF4clJUfB1dxI7GlGvxEIn0dU2t2PlzrPYsL8UznIp5k2IwJ/GhMPVSSZ2NKJehYVONqPscgte++ZHbDteiQBPF8yfFIkHhqvhLGexE3UHC51szsnyerzydSF2F11CoJcLHp/IYifqDhY62awjpbVY8V0Rdp2pZrETdQMLnWzer4u9r6czHh4TjpkjQ+HpohA7GpFNYaFTr3H0p1r8Z+c5fHu6Ch7OcswYEYKHx4QjyNtV7GhENoGFTr3OueomZO4uxuaj5TCZBKTEBeGRseEYEuwldjQiUbHQqdeqbmzD+v0l2JBbiroWPeJDvDE7KQxTYgPhouA8OzkeFjr1eq3tRmSfqMT63BLkVzTAx02BBxJDMGtkGEJ83cSOR2Q1LHSyG4Ig4HhZHTbkliIn7wL0RhPGRPTB9GFq3BMdwBOVyO6x0MkuXW5uxydHyrDpcDmKtE1QOssxNS4Q04eFICHU+7oLqxD1dix0smuCICCvvB6bjpThs+OVaNAZ0N/fHWnxwZgaF4TwPu5iRyTqMSx0chg6vRHbC6rwyZFy7Dl7CUaTgOggT6TEBWFKTCDn26nXY6GTQ6ppasNXpy4i58QF5BbXQBCA+BBvTIkJxF2avujHkTv1Qix0cnjaRh2+PHkROXmVOFxaC0EAolQemKzpi8mD+2JoiDekUs65k+1joRP9irZRh52FWmwv0GLP2Wro9Cb08XDCnYP6YuIgFUZH+vGSA2SzWOhEXWhtN2LP2Uv4tqAK3xVW4VJTO2RSCeJDvDEuqg/GRfVBnNobcq6LSjaChU7UDSaTgIILDdhVVI3dZy7hcOll6I0ClM5yjI70w9gofySF+yJS5cFDIkk0LHSiW9DSbsCB4svYfeYSdhdVo0jbBADwdXdCYj8fjAj3w8hwXwwO9ISM8+9kJXKxAxD1Rm5OckwcqMLEgSoAgLZBh4Mll3GwuOP29akqAIDSWY5h/XyQEOqD+BBvxKm94eXGOXiyDI7QiSygtrkdh0trcbC4BgeLL+NUZQMMpo7/av37uCM+xBvxoR0FPzjQE05yzsPT7WOhE1mBTm9EwYUGHP+pDsfL6nCivA6lNS0AACe5FIMClBgc4AlNUMdtUIASSh5NQzeJhU4kksvN7ThRXofjP9Wh4EIDCiobUFHX2vnzUF83aAI9MTjQE4MDlYjqq0Sorxvn5KlLLHQiG1Lfou8o9wsNOH2l5Iu0jdAbO/6bOsml6N/HHREqD0SpPBCp8kCUSol+fdy41ipxpyiRLfFyU2BUhB9GRfh1bms3mHD+UhPOaptQVNWEs9VNOKdtwvZTVWg3mgAAMqkEob5uCPNzQz8/d4T5uV25uUPt48qydxAsdCIb1zHH7olBAZ5XbTcYTSirbe0oem0jzmmbUVrTjM9PXkB1Y1vn4yQSIMjLtbPgQ33dEOTtgmBvVwT7uEKldOE0jp1goRP1UnKZFOF93BHexx13afpe9bPmNgN+utyC0ppmlNa0oKSmBT9dbsauM9W4UN8K068mWmVSCQI8Owo+yNsFQd6uCPJ2RbC3KwK8XKBSOsPHzYnXs+kFWOhEdsjdWX5lZ6rnNT/TG02oatChsk6HyrpWVFy5Vda1ouBCA7YXVKG53XjVc+RSCfyVzlApneGvdIHKs+N7lbKj8Dvuu8DPwwkKXgpBNCx0IgejkEmh9nGD2uf6138XBAENOgMqaltR1aCDtlEHbUMbtI1tHd83tuH0hQZUN7Z1zuH/mtJFDj93J/i4O3V8dXOCr3vHzcfdCb5uTvD1+OWr0lnOyyX0EBY6EV1FIpHAy1UBL1cFNEHXjvB/JggC6lv1HUXf0FH2NU3tuNzSjstXvtY2t+N8dTMut7SjrkV/3deRSSXwdJHD88p7eroo4Okq/9X3V27XeYyHsxyuChl/IVwhSqHn5OTgmWeegclkwrPPPov09HQxYhDRbZBIJPB2c4K3mxMG9FWafbzBaEJdqx61ze24/PPtStE3tOrRoNOjvlWPhlYDyi634pSu4cp2A4ymro+ulkgAdyc53J1lcHeWd37v4SzvuO8sh7tTx89+3ubm1PFzVycZXBUyuCh+89VJCieZtNf9orD6cegGgwEajQY7d+6Ep6cnEhIScODAAfj6+l738TwOncixCYKA5nbjlbLvuNVfKfqWdgOa2gxobjOguc3Y8bXdgKafv79yv7nNiKY2A9oN104RdUUiwVUl76yQwvVXxd9xk3bed5ZL4ayQwkkmg5NcCme59JqvzvJfftavjzv6eDj36L+V1UfoBw8eRHR0NIKDgwEAycnJ+PrrrzFjxgxrRyGiXkAikcDjyug62Nv1tl5LbzShpc2IpvaOsm9tN6JVb4Su82ZCq96I1nYjdAYjdO1G6Aymjvv6nx9rgk5vRG1L+y/b2o1oN5rQZui4decXx6vTY3H/8JDb+jy/ZfVCr6ys7CxzAFCr1aioqLB2DCJyQAqZFF5uUotf8VIQBLQbO4q9/Vcl//PXdqMRob49v26t1Qv9ejM8v52nyszMRGZmJgBAq9VaJRcRUU+RSCRwlsusfoau1Q8YDQ4OvmpEXl5ejsDAwKsek56ejtzcXOTm5kKlUlk7IhFRr2T1Qh8xYgTy8/NRUVGBxsZGfPHFF7jnnnusHYOIyO5YfcpFLpfj9ddfx8SJE2EymbB48WL4+fmZfyIREd0QL59LRGQneNEFIiI7wUInIrITLHQiIjth83Poffv2RXh4+C09V6vVOsxhj/ys9omf1X7d6uf19/dHdnb2dX9m84V+Oxxphyo/q33iZ7Vflvi8nHIhIrITdl3ojnRZXn5W+8TPar8s8XntesqFiMiR2PUInYjIkbDQiYjshF0Wek5ODgYOHIioqKjOy/Daq7KyMkyYMAEajQaxsbHYtGmT2JEsqqWlBWFhYcjIyBA7isUVFxdj4sSJ0Gg0iImJQXNzs9iRLOaNN95AdHQ0NBoNFixYcN3LbPdmaWlp8PHxwfTp0zu3/bzYT2RkJJYtW9YzbyTYGb1eL0RFRQnl5eVCQ0ODEBkZKdTU1Igdy2IqKyuFY8eOCYIgCFVVVUJwcLDQ1NQkbigLeuGFF4T7779feOaZZ8SOYnHjx48Xdu3aJQiCINTU1Ah6vV7kRJah1WqF/v37C62trYLBYBBGjx4t7Nu3T+xYPWrHjh3CZ599Jvz+97/v3DZ8+HDhxIkTgl6vF4YPHy6cPHnytt/H7kbov17iTqlUdi5xZ68CAwMRHx8PAFCpVPD19cXly5fFDWUhRUVFKCwsRHJysthRLO7UqVNQKBQYN24cAMDX1xdyuShruluFwWCATqeDXq+HXq+3uxOMJk6cCKXyl4W0KysrYTAYEBsbC7lcjpkzZ3Z5stDNsLtCd+Ql7g4fPgyTyYSQkJ5dp9BWZGRkYPny5WLHsIqioiJ4eHggNTUVCQkJePnll8WOZDH+/v7IyMhAaGgogoKCMHnyZERERIgdy6Is1VN2V+hCN5a4s0c1NTWYM2cOVq9eLXYUi9i2bRsGDBiAAQMGiB3FKvR6PXbv3o1Vq1Zh//792L59O7Zv3y52LIuora1FTk4OSkpKUFFRgX379mHXrl1ix7IoS/WU3RV6d5a4szdtbW1IS0vD888/j9GjR4sdxyJyc3Px0UcfoV+/fsjIyMA777zTczuSbJBarUZiYiJCQkLg7OyM5ORkHD9+XOxYFvHtt98iMjISvr6+cHV1xZQpU+z+EgCW6im7K3RHW+JOEATMnTsXkyZNwuzZs8WOYzHLly9HWVkZSkpK8Nprr+HRRx/FkiVLxI5lMYmJiaiqqkJtbS1MJhN27dqFwYMHix3LIkJCQrBv3z7odDoYjUZ8//33GDhwoNixLCooKAgymQx5eXkwGAzIyspCSkrKbb+u3e1lcbQl7vbu3YuNGzciNjYWW7duBQBs2LABMTEx4gaj2yKXy/Hyyy9j/PjxEAQBd999N6ZOnSp2LItISkpCcnIyhg4dCqlUijvvvBOpqalix+pR99xzD44ePYrm5mao1Wps2bIFK1euxIwZM6DT6TB79uwe+T/LU/+JiOyE3U25EBE5KhY6EZGdYKETEdkJFjoRkZ1goRMR2QkWOjms++67D59++mnn/czMTDz88MMiJiK6PTxskRzW2bNnMXXqVBw7dgzt7e1ITEzEnj17bunCUEajETKZzAIpibqPhU4O7cUXX4RCoUBtbS0iIiJw6NAhnD59GoIgYMWKFRgzZgxyc3Px9NNPo7W1FT4+Pvjggw8QGBiIpUuX4uLFizh79iw0Gg3S0tKwYMECSKVSKBQKHD58WOyPRw6GhU4OrbW1FQkJCXB3d8fEiRMxevRopKWloby8HFOmTMGJEyfQ0NAAd3d3yGQyfPjhhzh06BDeeOMNLF26FNu3b8fOnTvh5OSElJQULFiwAHfddRfq6+vh5eUl9scjB2N3p/4T3QxXV1fcf//96NOnD9577z18/fXX+Mc//gGg4wqW7e3tqK2txaxZs3D+/HkYDAaEhYV1Pv+//uu/4OTkBAAYM2YMnnvuOZw+fRr3338/C52sjjtFyeFJpVJIpVIIgoCcnBwcP34cx48fR3l5OZycnLBkyRJMmTIF+fn5WLduHdra2jqf6+bm1vn9c889h7Vr16KpqQmJiYkOcx1+sh0sdKIrJk+ejFWrVnXeP3HiBACgoaEBarUaAPD+++93+fxz584hLi4OL7zwAgYPHozi4mLLBib6DRY60RVLliyBVqtFTEwMNBpN5wLjGRkZWLhwIcaOHXvViPy3fl7oODY2FqGhoRg1apS1ohMB4E5RIiK7wRE6EZGdYKETEdkJFjoRkZ1goRMR2QkWOhGRnWChExHZCRY6EZGdYKETEdmJ/w+6oPThhdi7WgAAAABJRU5ErkJggg==",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYsAAAEECAYAAADZBhiGAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAArEAAAKxAFmbYLUAAAktElEQVR4nO3deVRU990/8PcsLMqmCKYsSiKDRCZMrCCMpklDYmMCqA8uUUikGmljo03a1IdK+vyU+PRI7Ik1Vk2XkEalDaZ4so3YY1KTJk2EuMUgieQBXCJMBFlkEQZnub8/gIkIODIwc4e579cJh5l7v3f4XI65b77f711kgiAIICIiugm52AUQEZHrY1gQEZFNDAsiIrKJYUFERDYxLIiIyCaGBRER2STpsJg3b57YJRARjQqSDovLly+LXQIR0agg6bAgIqJbw7AgIiKbGBZERGQTw4KIiGwSNSwOHDiA6OhoREVFIT8/v9/6o0ePQq1WQ6VSYdOmTdbl1dXViI+Ph0qlwurVq9F7L8SGhgYkJSUhKioKCxcuhMFgcNq+EBG5M9HCwmQy4dlnn8UHH3yAkydPYsuWLWhqaurTZs2aNSgsLERFRQV0Oh3Ky8sBANnZ2cjNzUVVVRXq6upQXFwMAMjLy8OiRYtQWVmJiIiIAQOIiIiGTinWD+7tNYSFhQEAkpOTcejQIaSnpwMA9Ho9TCYTNBoNACAjIwM6nQ5qtRolJSXYv38/ACAzMxM6nQ6pqanQ6XQ4duyYdfn69euxdu1aEfaORgtBECAIgADAYn3d8/3619etR89yi9CzPXraXvfaYn1t47P6VnNDbTdbO9D6/k8b6NfGxja2Hlgw1O371yzcdP2t1EC2+XkrMfU2vxH9TNHCQq/XW4MCAMLDw1FbW3vT9R999BEaGxsRGBgImUzWb7uWlhYEBAQM+HnkOIIgwGgW0Gk0w2A0o/OaGZ1GMzqu9X3faTTjmskCo7n3S8A1kwXXzBYYe5ZfMwvXrbf0rBdgNFlgFgRYLAJMFgEWQYDZ0v11/evuNrjudU/7nvfXt7fwoERuKuGOQPzjyVkj+pmihcVAz1zqDYCbrb/ZdtdvP9B7AMjPz7cOT9XX1w+taDcmCAJaO01ouNqFhrYuNF69huaOa2jtNKHNYESrwYg2gwmtnUa0GnqWdZpwtcuEDqMZZjuOvEq5DB4KOTwUMngq5fBQyK3fPRRyeCpk1tdKhQzecjkUcpn1Sy7reS2TQS6XQSnv/q6QXb8eUMjl3d9l362X96yXywCZDJBf929IBvQsl0EmA2S4/rWsp333657/IO9dP+BnXf853y3v/X69Af7J9lvWb6uBtun3GbKbrr+VnzNgbTYX2P6cgWsZaKnrcPHy4Os18od20cIiLCysz1/+NTU1SExMvOn6kJAQBAUFoampCYIgQCaTWZcDgL+/v7V3cf3y62VlZSErKwsAoNVqHbV7LsVktqCurQu1zZ3QX+lE7ZVO1PS8vtzWhcarXWi6eg1G80BB3P0Pz9/bA37eSviP8cD4sR6ICBwLP28lfL2VGOuphLeHAmM8FBjjKe/5ruz+3rOsd72nsicQ5HLI5S7+fxwRWYkWFgkJCSgvL0dtbS38/f1x8OBBbNiwwbo+NDQUCoUCZWVliImJQWFhIV599VXIZDJotVoUFxcjNTUVe/fuxRNPPAEASE1NRUFBAdauXYu9e/dK7t5PBqMZFZfaUF3fjqrL7aiqb0f15XZ809gB03V/+SvkMnzP3xth48bgjmAfzLx9PIJ8vTDB1wsTfD0R5OuFIF9PjBvrCT8vJQ/qRASZmM/gfvfdd7Fu3TpYLBZkZ2fjpz/9KZKTk5Gfn4/Q0FCUlpZi1apVMBgMWL58OXJzcwEAlZWVWLZsGa5cuYIHH3wQf/rTnyCXy3H58mUsXrwYtbW1uOuuu1BYWIgxY8YM+vO1Wi1KS0udtLcjy2IRcOZSK05dvIKyiy0oq23B/9W1WYeDfDwViJzoC1WwL6YE+yB8/FiEjR+DsHFjMNHPC0oFL7EholsnaliIbbSFxcWmDvynsgGfVjfgSFUDmjuMAIDQAG/EhgdAEz4OsWEBiLrNF9/z93b5cV8iGj1EG4aiW3OxqQPFp79Fcdm3OF3bAgCYEuSDFE0I7okMQtzt4zHRz1vkKonI3TEsXJDRbMH7X9WhoOQCSs42Qi7rPhXufxeo8cC02xA2bvChNSIiR2BYuBCD0YzXP/sGf/n4LC61GhAZ7ION82KQoglh74GIRMWwcAEWi4CiExex9b3/Q31bFx64cyJ+/+jdmBU5gfMOROQSGBYiO/NtK37z1mmc/OYK7o0KwiuZ8bh70jixyyIi6oNhIRJBEFBQegG/PXAGE3w98afHZ2Cu+nvsSRCRS2JYiKDzmhnrir5A8elvkaoJQd7CWPh5e4hdFhHRoBgWTnal4xqe2H0MZTUt+N//uguPJ05mb4KIXB7DwolaDUakv/IZzjdcRf6P43F/9ESxSyIiuiUMCycxGM34yZ7jOHu5HQWrEpFwR6DYJRER3TKGhZP8v7fLcfxCM/78eByDgohGHd5Nzgne/rwWRSdq8N9zozEn5jaxyyEiGjKGhYNdbOrAb946jfumBuOn904RuxwiIrswLBzsed2XUCrk2Lrkbj4XgohGLYaFA31YUY9/nanHf8+NRrCfl9jlEBHZjWHhIIIg4MX3vsbU23yRnjBZ7HKIiIaFYeEg731Vhy/1rfjlnKlQcPiJiEY5hoWDvPqfc4ia6Iu56u+JXQoR0bAxLBzgzLetOHq+CZmzb+ekNhG5BYaFA/z9swvw9VIi7fthYpdCRDQiGBYjzGS2oLjsW6TEhsDXixfIE5F7YFiMsCPVjWjuMCL17hCxSyEiGjEMixFWXPYtAn08MWvKBLFLISIaMQyLESQIAj74uh5zpk2EUsFfLRG5Dx7RRlBlfTsut3XhB1HBYpdCRDSiGBYj6JPKBgDA7EgOQRGRe2FYjKAj1Q2YFuKPIF/eB4qI3AvDYoQIgoDPzjVxYpuI3BLDYoRcaOxAm8GEuycFiF0KEdGIY1iMkHJ9CwDgrjCGBRG5H4bFCCmvbYWPpwJ3TPARuxQiohHHsBgh5bUtUIcG8MaBROSWGBYjQBAElOtboA7zF7sUIiKHYFiMgMttXbjSYcS0EIYFEbknhsUION/YAQC4nfMVROSmGBYj4ELjVQBAxISxIldCROQYDIsR8E1TB7w95Jjoxyu3icg9iRIWR48ehVqthkqlwqZNmwZsU11djfj4eKhUKqxevRqCIAAAGhoakJSUhKioKCxcuBAGgwEAcODAAdx1112Qy+UoLy932r4A3RfkTQ4cC5mMZ0IRkXsSJSzWrFmDwsJCVFRUQKfTDXhwz87ORm5uLqqqqlBXV4fi4mIAQF5eHhYtWoTKykpEREQgPz8fABAdHY39+/fjvvvuc+q+AMCFpg5MDuR8BRG5L6eHhV6vh8lkgkajgVKpREZGBnQ6XZ82giCgpKQEKSkpAIDMzExrG51Oh+XLl/dbHhUVhTvvvNOJe/Kdbxqvcr6CiNyaKGERFhZmfR8eHo7a2to+bRobGxEYGGgd1rm+TUtLCwICAgbd1tlaDUY0dxgZFkTk1pSO+uC4uDh0dXX1W75r165+y24c6++dnxiozY1thzpPkJ+fbx26qq+vH9K2A7nY1H3a7KRAhgURuS+HhcWJEycGXK7X6/v0BmpqahASEtKnTVBQEJqamiAIAmQyWZ82/v7+1t7FQNvakpWVhaysLACAVqsd0rYDqWvtnmAPCfAe9mcREbkqpw9DhYaGQqFQoKysDCaTCYWFhZg3b16fNjKZDFqt1jqpvXfvXmub1NRUFBQU9FsulvrW7t7TRD+GBRG5L1HOhtq5cyfS09MRHR2N5ORkxMbGAuj+q//48eMAgC1btmDjxo2IjIxEcHCwdbI7JycHRUVFUKlUOHfunLWXcOjQIYSHh6OkpARz5sxBenq6U/alvq0LHgoZxo/1cMrPIyISg0wYaIJAIrRaLUpLS4f1Gb956zT+/fVlfLr+gRGqiojI9fAK7mGqb+tCMK/cJiI3x7AYpssMCyKSAIbFMF3puIbAsZ5il0FE5FAMi2FqunoN43w4uU1E7o1hMQwmswWtBhN7FkTk9hgWw9DSaQQAjGdYEJGbY1gMQ3NHd1iM4zUWROTmGBbD0NxxDQAw3oc9CyJybwyLYWi+2hMW7FkQkZtjWAxDm8EEAPAfw7AgIvfGsBiG9q7usPDzYlgQkXtjWAxDe5cJCrkM3h78NRKRe+NRbhjaDCb4eimH/AAmIqLRZkhh8e233+LIkSMDPslOitq7jPD1ctjzo4iIXIbNI11CQgIOHz6Mq1evIiEhAdOmTUNERAReeeUVZ9Tn0tp7ehZERO7OZs/CaDTCz88PRUVFeOqpp/Dee+/h2LFjzqjN5bV3meHrzbAgIvdnMyzMZjMOHz6MPXv2IDU1FQBgMpkcXthowGEoIpIKm2Gxfft2bN++HUuWLEFsbCzOnj2LpKQkZ9Tm8tq7TOxZEJEk2DzSJSUlWcOhq6sL3t7e2LFjh8MLGw3aDSb4sWdBRBJgs2eRlpaGtrY2tLS0YNq0aXjwwQexYcMGZ9Tm8tq7zBjrybAgIvdnMyzOnz8PPz8/7N+/H+np6fjqq6/w9ttvO6E012cwmjHGk5eqEJH7s3mk6+rqQnV1NV5//XXMnz+fF6Bdx2A0w1upELsMIiKHsxkWGzZsQFpaGqZOnYrExEScPXsWKpXKGbW5NJPZApNFwBhPhgURuT+bA+7Lli3DsmXLrO+nTJmCN99806FFjQYGkwUA4OXBsCAi92ezZ/HNN99gwYIFCA0NRVhYGNLS0vDNN984ozaXZjCaAQDeSs5ZEJH7s3mkW7FiBR577DHo9XrU1tYiIyMDK1ascEJprs0aFuxZEJEE2AyLxsZGPProo9b3S5YsQWNjo0OLGg0Mxu5hKIYFEUmBzbCIiIjAiy++iEuXLuHSpUvYunUrJk+e7IzaXNp3PQsOQxGR+7N5pHvttddw4cIFPPLII3jkkUdw4cIF7N692wmlubYuE4ehiEg6bJ4NNWHCBN7eYwCd13qGoXidBRFJwKBhsWTJkptegPePf/zDIQWNFhyGIiIpGTQs1q5d68w6Rh0Dh6GISEIGDYsf/vCHzqxj1Ok9G8qLPQsikgAe6ezUOww1hj0LIpIAhoWdeFEeEUkJw8JOXSYL5DLAQ8FfIRG5P5unzgYHB/c7K8rf3x8zZszACy+8gClTpjisOFdmNFsYFEQkGTaPdk8++SQ2b96Ms2fP4uzZs8jLy8Njjz2GRx99FCtXrrTrhx49ehRqtRoqlQqbNm0asE11dTXi4+OhUqmwevVqCIIAAGhoaEBSUhKioqKwcOFCGAwGAMDWrVsxbdo0aDQapKWlobW11a7abpXJLDAsiEgybB7t3nvvPWRlZcHX1xe+vr5YtWoV/vnPf2Lx4sW4cuWKXT90zZo1KCwsREVFBXQ6HcrLy/u1yc7ORm5uLqqqqlBXV4fi4mIAQF5eHhYtWoTKykpEREQgPz8fABAXF4fPP/8cZWVlUKvVePHFF+2q7VYZLRYoFXwQFBFJg82w8PHxwR/+8AfU1dWhrq4OO3bsgI+PDywWCxSKoU/u6vV6mEwmaDQaKJVKZGRkQKfT9WkjCAJKSkqQkpICAMjMzLS20el0WL58eb/l999/P7y9vQEAM2bMQG1t7ZBrGwqTWYBSzp4FEUmDzaPdG2+8ga+//hoPP/ww5s6di4qKCuzbtw9GoxGFhYVD/oF6vR5hYWHW9+Hh4f0O7I2NjQgMDLTOlVzfpqWlBQEBAYNuCwC7d+/GQw89NOTahsJktsCDPQsikgibE9wTJ07Erl27BlwXHR096HZxcXHo6urqt3ygz7pxAr13fmKgNje2vfH9Sy+9BABYunTpgHXl5+dbh67q6+sHqd42o0XgMBQRSYbNsDhz5gx+//vf4/z58zCbzdblH3zwwU23O3HixIDLex+i1KumpgYhISF92gQFBaGpqQmCIEAmk/Vp4+/vb+1d3LitTqdDQUEBPvroo0HrysrKQlZWFgBAq9XedB9uxmS2wIPDUEQkETbDYunSpfjlL3+Jn//853bNUdwoNDQUCoUCZWVliImJQWFhIV599dU+bWQyGbRaLYqLi5Gamoq9e/fiiSeeAACkpqaioKAAa9euxd69ezFv3jwA3eG0bt06HD58GL6+vsOu0xaTmT0LIpIOm38ae3t7Y+XKldBoNFCr1dav4di5cyfS09MRHR2N5ORkxMbGAuj+q//48eMAgC1btmDjxo2IjIxEcHCwdbI7JycHRUVFUKlUOHfunLWX8Otf/xqtra1ITU3F9OnTsWbNmmHVaIvRwgluIpIOmTDQBMF11q9fD29vbyxYsABeXl7W5TExMQ4vztG0Wi1KS0vt2vZnfzsB/ZVOvLP2ByNcFRGR67E5DPXZZ58BQJ95AJlMZnPOwt0ZzQKUvCiPiCTCZlh8+OGHzqhj1DFZLFDKOWdBRNIwaFgUFRVhyZIlePnllwdc/9RTTzmsqNGA94YiIikZNCyampoAAJcvX3ZaMaOJ0SxgrCfDgoikYdCwePLJJwEAGzduBACYTCYolTZHrSTDZLZAKfcQuwwiIqew+adxSUkJpk+fjsjISABAWVkZnnnmGYcX5upMFgGeSs5ZEJE02AyLZ555BsXFxQgMDAQAaDQaHD582OGFuTojbyRIRBJi82gnk8n63PgPAOQ8SHYPQ/EKbiKSCJuTEHfeeSfeeecdCIKAmpoa7Ny5E/Hx8c6ozaWZLALvDUVEkmHzaPfyyy+jtLQUSqUSCxYsgCAI2LFjhzNqc2lG9iyISEJs9ix8fHyQl5eHnJwcyGQy+Pn5OaMul8fHqhKRlNg82pWWliI2NhYJCQmYOXMmNBoNjh496ozaXBqv4CYiKbHZs8jKysKePXsQFxcHADh58iQyMzMHfG62lPDeUEQkJTaPduPGjbMGBdD9fOtx48Y5sqZRgY9VJSIpGbRncfDgQQBAbGws0tLSsHTpUshkMhQVFQ3rCXPugs+zICIpuemNBHuNGzcOhw4dAgD4+flZ7xslZbzOgoikZNCweO2115xZx6hisQiwCOAwFBFJxqBhkZ2dfdMNf/e73414MaOF0WIBAA5DEZFkDBoWw33OtjszW7qfRMthKCKSikHD4sc//rEz6xhVerICchnDgoikYdCwmDlzJmQ3ORhK+cI8i9CdFgwLIpKKQcNi//79zqxjVBG6pyzAC7iJSCoGnaGNiIiwfl26dAmffvopIiIi4O/vD4VC4cwaXQ57FkQkNTZv95Gbm4uTJ0+ioqICGRkZ6OjowLJly/DJJ584oz6X1BsWzAoikgqb536+/fbbeOedd+Dj4wMACAsLQ2trq8MLc2W9E9w3m9MhInInNsPCy8sLwHcHxitXrkj+SXkCeoehRC6EiMhJbB71f/azn2Hp0qVoaGjAb3/7W9x7771Yt26dM2pzWQJPnSUiiRl0zqK8vBxqtRorVqxAYmIiDh8+DEEQsG/fPslfsMc5CyKSmkHDIisrC2fPnsX06dMxa9YszJo1C4mJiRg/frwz63NJvCiPiKRm0GGo0tJS1NTUYNOmTRg/fjx2796NuLg4xMTEYNWqVc6s0eVYLOxZEJG03PTUWU9PT2i1WoSHhyM0NBShoaE4ePAgTp8+7az6XBLnLIhIagYNi23btqGkpAR6vR6TJk1CYmIiFi9ejLy8POsZUlLFs6GISGoGDYs///nP8PHxwfz58zFr1iwkJCTwcao9eJ0FEUnNoGFRUVGBK1euoLS0FEeOHMFLL72E5uZmREdHQ6vVYvXq1c6s06Xwdh9EJDU3nbMYN24cHn74YcyaNQulpaUoKSlBQUEB9u3bJ+mwEAQOQxGRtAwaFq+88gpKSkpQUlKC9vZ2JCYmIjExEXv27EF8fLwza3Q53w1DiVsHEZGzDBoWX331FebOnYvc3FxMnjzZmTW5vO8uymNaEJE03PRsKBoYT50lIqkR5Y6AR48ehVqthkqlwqZNmwZsU11djfj4eKhUKqxevdo6T9DQ0ICkpCRERUVh4cKFMBgMAIDt27dDo9Fg+vTpmDt3Lurq6hxWv4VzFkQkMaKExZo1a1BYWIiKigrodDqUl5f3a5OdnY3c3FxUVVWhrq4OxcXFAIC8vDwsWrQIlZWViIiIQH5+PgBg5cqVKCsrw6lTp7BgwQJs3rzZYfWzZ0FEUuP0sNDr9TCZTNBoNFAqlcjIyIBOp+vTRhAElJSUICUlBQCQmZlpbaPT6bB8+fJ+y/39/a3bt7W1OXQ+wTpn4bCfQETkWmw+KW+k6fV6hIWFWd+Hh4fjo48+6tOmsbERgYGB1gN+eHg4amtrAQAtLS0ICAjotxwAXnjhBfzxj3+Er69vv88cSbwoj4ikxmE9i7i4ONx11139vq5evdqv7Y0H3d75iYHa3Nj2+vfr16/HhQsXsGrVKuzYsWPAuvLz86HVaqHValFfXz/k/QI4Z0FE0uOwnsWJEycGXK7X6/v0BmpqahASEtKnTVBQEJqamiAIAmQyWZ82/v7+1t7FQNsCwGOPPYYHHngAzz//fL91WVlZyMrKAgBotVq79s06Z8G0ICKJcPqcRWhoKBQKBcrKymAymVBYWIh58+b1aSOTyaDVaq2T2nv37rW2SU1NRUFBQb/llZWV1u3fffdd3HnnnQ7bB17BTURSI8rZUDt37kR6ejqio6ORnJyM2NhYAN1/9R8/fhwAsGXLFmzcuBGRkZEIDg62Tnbn5OSgqKgIKpUK586ds/YStm7dCrVajenTp+Ott97CSy+95LD6OWdBRFIjEwaaIJAIrVaL0tLSIW9XerYRy/5Sireemo3vT+aTA4nI/YnSsxjteNdZIpIahoUdeFEeEUkNw8IOAu86S0QSw7CwA4ehiEhqGBZ2sIYFf3tEJBE83NnBOgzFu0MRkUQwLOzA230QkdQwLOzAi/KISGoYFnbg7T6ISGoYFnaw8DoLIpIYhoUdensWzAoikgqGhR3YsyAiqWFY2MHCngURSQzDwg68gpuIpIZhMQwMCyKSCoaFHXhRHhFJDcPCDhZLzwuGBRFJBMPCDpyzICKpYVjYgQ8/IiKpYVjYgXMWRCQ1DAs79HQseCNBIpIMhoUdeFEeEUkNw8IOvN0HEUkNw8IOvEU5EUkNw8IOFgtPnSUiaWFY2OG7J+WJWwcRkbMwLOzQezYUexZEJBUMCztYH34kch1ERM7CsLADb/dBRFLDsLAD5yyISGoYFnawCAJkMl7BTUTSwbCwgyBwCIqIpIVhYQdBEDi5TUSSwrCwg4U9CyKSGIaFHXrnLIiIpIJhYQf2LIhIahgWdhAEgTcRJCJJESUsjh49CrVaDZVKhU2bNg3Yprq6GvHx8VCpVFi9erX1qumGhgYkJSUhKioKCxcuhMFg6LPdjh07IJPJ0N7e7rD6LYLAngURSYooYbFmzRoUFhaioqICOp0O5eXl/dpkZ2cjNzcXVVVVqKurQ3FxMQAgLy8PixYtQmVlJSIiIpCfn2/d5vLlyzh48CAmT57s0PoFAbzXBxFJitPDQq/Xw2QyQaPRQKlUIiMjAzqdrk8bQRBQUlKClJQUAEBmZqa1jU6nw/Lly/stB4CcnBw8//zzDr9YjnMWRCQ1ooRFWFiY9X14eDhqa2v7tGlsbERgYKD1oH99m5aWFgQEBPRbXlpaCovFgoSEBIfvA+csiEhqlI764Li4OHR1dfVbvmvXrn7LbuwJ9M5PDNTmxrYymQwWiwU5OTl4/fXXbdaVn59vHbqqr6+32X4gnLMgIqlxWFicOHFiwOV6vb5PT6KmpgYhISF92gQFBaGpqan7SmmZrE8bf39/a++id3lbWxvKy8sxa9Ys62eq1WqcPn0a/v7+fT47KysLWVlZAACtVmvXvlkE3heKiKTF6cNQoaGhUCgUKCsrg8lkQmFhIebNm9enjUwmg1artU5q792719omNTUVBQUFfZYHBATg8uXLOH/+PM6fP4/w8HB8+eWX/YJipFg4DEVEEiPK2VA7d+5Eeno6oqOjkZycjNjYWADdf/UfP34cALBlyxZs3LgRkZGRCA4Otk525+TkoKioCCqVCufOnbP2EpxJEHh7ciKSFpkw0ASBRGi1WpSWlg55u43vlOO9r+pQkvOgA6oiInI9vILbDjx1loikhmFhB95IkIikhmFhB/YsiEhqGBZ2ENizICKJYVjYgY9VJSKpYVjYgXMWRCQ1DruC2509laRCu8EkdhlERE7DsLDDHUE+YpdARORUHIYiIiKbGBZERGQTw4KIiGxiWBARkU0MCyIisolhQURENjEsiIjIJkk/z+K2227DHXfcYde29fX1mDhx4ghX5Jq4r+5LSvvLfb01wcHB0Ol0/ZZLOiyGw94HJ41G3Ff3JaX95b4OD4ehiIjIJoaFncR49rdYuK/uS0r7y30dHg5DERGRTexZEBGRTQwLIiKyiWFhhwMHDiA6OhpRUVHIz88XuxyHuXjxIu6//37ExMRAo9GgqKhI7JIcrqOjAxEREVi3bp3YpTjUuXPnkJSUhJiYGMTGxuLq1atil+Qw27Ztg1qtRkxMDJ5++mm428h7Wloaxo8fj8WLF1uXHT16FGq1GiqVCps2bRqZHyTQkBiNRiEqKkqoqakRWltbBZVKJTQ2NopdlkPo9Xrh888/FwRBEOrq6oSwsDChvb1d3KIc7LnnnhOWLFki/OpXvxK7FIe67777hI8//lgQBEFobGwUjEajyBU5Rn19vTBlyhShs7NTMJlMwuzZs4UjR46IXdaI+uCDD4R3331XWLRokXVZfHy88MUXXwhGo1GIj48XTp8+Peyfw57FEPUmdlhYGPz8/JCcnIxDhw6JXZZDhISEYPr06QCAiRMnIjAwEE1NTeIW5UCVlZWoqKhAcnKy2KU41JdffgkPDw/ce++9AIDAwEAole77HDSTyQSDwQCj0Qij0eh2F+YlJSXBz8/P+l6v18NkMkGj0UCpVCIjI2PAi+yGimExRHq9HmFhYdb34eHhqK2tFbEi5zh+/DgsFgsmTZokdikOs27dOuTl5YldhsNVVlbC19cX8+fPx4wZM7B582axS3KY4OBgrFu3DpMnT0ZoaCjmzJmDyMhIsctyKEcdoxgWQyQMMN4pk8lEqMR5GhsbkZmZib/85S9il+Iw77zzDqZOnYqpU6eKXYrDGY1G/Oc//8GuXbtQUlKC999/H++//77YZTlEc3MzDhw4gPPnz6O2thZHjhzBxx9/LHZZDuWoYxTDYojCwsL6pHRNTQ1CQkJErMixurq6kJaWhpycHMyePVvschymtLQU+/btw+23345169bhlVdeGbmJQRcTHh6OmTNnYtKkSfDy8kJycjJOnToldlkO8a9//QsqlQqBgYEYM2YMUlJS3P6WH446RjEshighIQHl5eWora1FW1sbDh48iLlz54pdlkMIgoAVK1bggQcewPLly8Uux6Hy8vJw8eJFnD9/Hi+++CJ+8pOfYMOGDWKX5RAzZ85EXV0dmpubYbFY8PHHH2PatGlil+UQkyZNwpEjR2AwGGA2m/Hvf/8b0dHRYpflUKGhoVAoFCgrK4PJZEJhYSHmzZs37M9131ktB1Eqldi6dSuSkpJgsViQnZ2NCRMmiF2WQ3z66ad44403oNFo8PbbbwMACgoKEBsbK25hNCxKpRKbN2/GfffdB0EQ8NBDDyE1NVXsshxCq9UiOTkZ3//+9yGXy/Hggw9i/vz5Ypc1oubOnYuTJ0/i6tWrCA8Px1tvvYWdO3ciPT0dBoMBy5cvH5H/Z3m7DyIisonDUEREZBPDgoiIbGJYEBGRTQwLIiKyiWFBREQ2MSyIHOCRRx7Bm2++aX2fn5+PlStXilgR0fDw1FkiB6iqqkJqaio+//xzXLt2DTNnzsQnn3xi103szGYzFAqFA6okunUMCyIH+Z//+R94eHigubkZkZGROHbsGM6cOQNBELB9+3bcc889KC0txbPPPovOzk6MHz8ef//73xESEoLc3FxcunQJVVVViImJQVpaGp5++mnI5XJ4eHjg+PHjYu8eSQzDgshBOjs7MWPGDPj4+CApKQmzZ89GWloaampqkJKSgi+++AKtra3w8fGBQqHA66+/jmPHjmHbtm3Izc3F+++/jw8//BCenp6YN28enn76afzoRz9CS0sLAgICxN49khje7oPIQcaMGYMlS5YgKCgIe/bswaFDh/D8888D6L6T77Vr19Dc3IzHH38cZ8+ehclkQkREhHX7BQsWwNPTEwBwzz33YP369Thz5gyWLFnCsCCn4wQ3kQPJ5XLI5XIIgoADBw7g1KlTOHXqFGpqauDp6YkNGzYgJSUF5eXl2L17N7q6uqzbjh071vp6/fr1+Otf/4r29nbMnDlTEs9QIdfCsCBygjlz5mDXrl3W91988QUAoLW1FeHh4QCAv/3tb4NuX11djbvvvhvPPfccpk2bhnPnzjm2YKIbMCyInGDDhg2or69HbGwsYmJikJ+fD6D76Xy/+MUv8IMf/KBPT+JG27Ztg1qthkajweTJkzFr1ixnlU4EgBPcRER0C9izICIimxgWRERkE8OCiIhsYlgQEZFNDAsiIrKJYUFERDYxLIiIyCaGBRER2fT/AfvWnj2bcUfiAAAAAElFTkSuQmCC",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "df = generate_households(num_households=1, exp=5000, v=0.3, fix_seed=False)\n",
- "\n",
- "default_parameters = {'recovery_rate': 0.5, \n",
- " 'years_to_recover': 10, \n",
- " 'income_and_expenditure_growth': 0.02,\n",
- " 'average_productivity': 0.35,\n",
- " 'consumption_utility': 1.5,\n",
- " 'discount_rate': 0.04}\n",
- "\n",
- "consumption, consumption_unaffected, consumption_loss, consumption_loss_npv, wellbeing = calculate_consumption_recovery(df, default_parameters, print_statistics=True)\n",
- "\n",
- "ax = consumption_loss.T.plot(legend=False)\n",
- "plt.xlabel('Years')\n",
- "plt.ylabel('Consumption loss');\n",
- "sns.despine()\n",
- "\n",
- "ax = wellbeing.T.plot(legend=False)\n",
- "plt.xlabel('Years')\n",
- "plt.ylabel('Wellbeing loss');\n",
- "sns.despine()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 22,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(5000, -0.034520709496898866, 6032.746643707037, 9464.387539258825)"
- ]
- },
- "execution_count": 22,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "consumption_utility = 1.5\n",
- "discount_rate = 0.04\n",
- "weighted_average_expenditure = df['exp'].values[0]\n",
- "total_wellbeing_loss = wellbeing.replace([np.inf, -np.inf], np.nan).dropna(axis=1).sum(axis=1).values[0]\n",
- "total_asset_damage = df['keff'].multiply(df['v']).values[0]\n",
- "total_consumption_loss = consumption_loss.sum(axis=1).values[0]\n",
- "total_consumption_loss_npv = consumption_loss_npv.sum(axis=1).values[0]\n",
- "weighted_average_expenditure, total_wellbeing_loss, total_asset_damage, total_consumption_loss_npv"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 45,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2.82842712474619e-06"
- ]
- },
- "execution_count": 45,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "welfare = math.pow(weighted_average_expenditure, -consumption_utility)\n",
- "welfare"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 42,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "-0.0282842712474619"
- ]
- },
- "execution_count": 42,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "welfare = (math.pow(weighted_average_expenditure, 1 - consumption_utility)) / (1 - consumption_utility)\n",
- "welfare"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 39,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1.9943431457505076"
- ]
- },
- "execution_count": 39,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "welfare = (math.pow((1 / discount_rate) * weighted_average_expenditure, 1 - consumption_utility) - 1) / (1 - consumption_utility)\n",
- "welfare"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 47,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "12204.91388831402"
- ]
- },
- "execution_count": 47,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "tot_consum_equiv_loss = - (total_wellbeing_loss / welfare)\n",
- "tot_consum_equiv_loss"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 48,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(0.6374154290156501, 0.49428834147558226)"
- ]
- },
- "execution_count": 48,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "total_asset_damage / total_consumption_loss_npv, total_asset_damage / tot_consum_equiv_loss"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "unbreakable",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.18"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/setup.py b/setup.py
index 78d9984..e3ec961 100644
--- a/setup.py
+++ b/setup.py
@@ -1,10 +1,10 @@
from setuptools import find_packages, setup
setup(
- name='unbreakable',
+ name="unbreakable",
packages=find_packages(),
- version='0.3.0',
- description='Unbreakable: Building the Resilience of the Poor in the Face of Natural Disasters a Simulation Model',
- author='Mikhail Sirenko and Bramka Arga Jafino',
- license='CC BY 3.0 IGO',
+ version="0.4.0",
+ description="Unbreakable: A Simulation Tool for Estimating Socio-Economic Impacts of Disaster on Households",
+ author="Mikhail Sirenko and Bramka Arga Jafino",
+ license="CC BY-SA 4.0",
)
diff --git a/unbreakable/__init__.py b/unbreakable/__init__.py
index 066d9f5..ae675c2 100644
--- a/unbreakable/__init__.py
+++ b/unbreakable/__init__.py
@@ -1,3 +1,3 @@
"""
.. include:: ../README.md
-"""
\ No newline at end of file
+"""
diff --git a/unbreakable/analysis/analyzer.py b/unbreakable/analysis/analyzer.py
deleted file mode 100644
index c07cb7e..0000000
--- a/unbreakable/analysis/analyzer.py
+++ /dev/null
@@ -1,472 +0,0 @@
-import pandas as pd
-import numpy as np
-import ast
-import geopandas as gpd
-from tqdm import tqdm
-import yaml
-
-
-def prepare_outcomes(results: tuple, add_policies: bool, add_uncertainties: bool) -> pd.DataFrame:
- '''Convert outcomes dict in (EMA Workbench format) into a pd.DataFrame.
-
- Args:
- results (tuple): The results of the experiments in the EMA Workbench format.
- add_policies (bool): Whether to add policy values.
- add_uncertainties (bool): Whether to add uncertainty values.
-
- Returns:
- pd.DataFrame: Outcomes.
- '''
- # Read outcome names from a yaml file
- with open("../../unbreakable/analysis/outcomes.yaml", "r") as f:
- outcome_names = yaml.safe_load(f)
-
- policy_names = ['current_policy']
- uncertainty_names = []
-
- experiments, _ = results
- experiments['random_seed'] = experiments['random_seed'].astype(int)
- experiments['scenario'] = experiments['scenario'].astype(int)
-
- if len(experiments['random_seed'].unique()) != experiments['scenario'].max() - experiments['scenario'].min() + 1:
- print('Warning! Random seeds are not unique.')
-
- base_columns = ['scenario', 'policy', 'region', 'random_seed']
- if add_policies:
- if add_uncertainties:
- columns = base_columns + \
- policy_names + uncertainty_names + outcome_names
- else:
- columns = base_columns + \
- policy_names + outcome_names
- else:
- if add_uncertainties:
- columns = base_columns + \
- uncertainty_names + outcome_names
- else:
- columns = base_columns + outcome_names
-
- scenarios = results[0]['scenario'].values
- n_scenarios = results[0]['scenario'].unique().size
-
- policies = results[0]['policy'].values
- n_policies = results[0]['policy'].unique().size
-
- random_seeds = results[0]['random_seed'].values
- n_regions = len(results[1].keys())
-
- if add_policies:
- policy_values = results[0][policy_names].values
-
- if add_uncertainties:
- uncertainty_values = results[0][uncertainty_names].values
-
- n_columns = len(columns)
- n_rows = n_scenarios * n_policies * n_regions
- outcomes = np.zeros((n_rows, n_columns), dtype=object)
-
- i = 0 # To iterate over rows = scenarios * policies * regions
- for region, region_outcomes in results[1].items():
- # To iterate over rows = scenarios * policies (experiments dataframe)
- k = 0
- # We reset k every time we change region
- for arr in region_outcomes:
- # The first 3 rows for scenario, policy and region
- outcomes[i, 0] = scenarios[k]
- outcomes[i, 1] = policies[k]
- outcomes[i, 2] = region
- outcomes[i, 3] = random_seeds[k]
-
- if add_policies:
- if add_uncertainties:
- # Add policy values
- # From 4 to 4 + len(policy_names) policy values
- for j, name in enumerate(policy_names):
- outcomes[i, 4 + j] = policy_values[k, j]
-
- # Add uncertainty values
- # From 4 + len(policy_names) to 4 + len(policy_names) + len(uncertainty_names) uncertainty values
- for j, name in enumerate(uncertainty_names):
- outcomes[i, 4 + len(policy_names) +
- j] = uncertainty_values[k, j]
-
- # Add outcomes
- # From 4 + len(policy_names) + len(uncertainty_names) to 4 + len(policy_names) + len(uncertainty_names) + len(outcome_names) outcomes
- l = 4 + len(policy_names) + len(uncertainty_names)
- for v, name in zip(arr, outcome_names):
- if name in ['weighted_vuln_quint', 'weighted_vuln_dec', 'years_in_poverty']:
- outcomes[i, l] = ast.literal_eval(v)
- else:
- outcomes[i, l] = v
- l += 1
- else:
- # Add policy values
- # From 4 to 4 + len(policy_names) policy values
- for j, name in enumerate(policy_names):
- outcomes[i, 4 + j] = policy_values[k, j]
-
- # Add outcomes
- # From 4 + len(policy_names) to 4 + len(policy_names) + len(outcome_names) outcomes
- l = 4 + len(policy_names)
- for v, name in zip(arr, outcome_names):
- if name in ['weighted_vuln_quint', 'weighted_vuln_dec', 'years_in_poverty']:
- outcomes[i, l] = ast.literal_eval(v)
- else:
- outcomes[i, l] = v
- l += 1
- else:
- if add_uncertainties:
- # Add uncertainty values
- # From 4 to 4 + len(uncertainty_names) uncertainty values
- for j, name in enumerate(uncertainty_names):
- outcomes[i, 4 + j] = uncertainty_values[k, j]
-
- # Add outcomes
- # From 4 + len(uncertainty_names) to 4 + len(uncertainty_names) + len(outcome_names) outcomes
- l = 4 + len(uncertainty_names)
- for v, name in zip(arr, outcome_names):
- if name in ['weighted_vuln_quint', 'weighted_vuln_dec', 'years_in_poverty']:
- outcomes[i, l] = ast.literal_eval(v)
- else:
- outcomes[i, l] = v
- l += 1
- else:
- # Add outcomes
- # From 4 to 4 + len(outcome_names) outcomes
- l = 4
- for v, name in zip(arr, outcome_names):
- if name in ['weighted_vuln_quint', 'weighted_vuln_dec', 'years_in_poverty']:
- outcomes[i, l] = ast.literal_eval(v)
- else:
- outcomes[i, l] = v
- l += 1
- k += 1 # increase row index to get next experiment for the current region
- i += 1 # increase row index of the outcomes dataframe
- outcomes = pd.DataFrame(outcomes, columns=columns)
-
- # Iterate over the columns and try to convert them to numeric if possible
- for col in outcomes.columns:
- try:
- outcomes[col] = pd.to_numeric(outcomes[col])
- except:
- pass
-
- # Convert pct columns to percentage
- outcomes['annual_avg_consum_loss_pct'] = outcomes['annual_avg_consum_loss_pct'] * 100
- outcomes['initial_poverty_gap'] = outcomes['initial_poverty_gap'] * 100
- outcomes['new_poverty_gap_all'] = outcomes['new_poverty_gap_all'] * 100
- outcomes['new_poverty_gap_initial'] = outcomes['new_poverty_gap_initial'] * 100
- outcomes['n_poor_ratio'] = outcomes['n_poor_initial'].div(
- outcomes['tot_pop']).round(2) * 100
-
- # Calculate the percentage of new poor
- outcomes = outcomes.assign(n_new_poor_increase_pp=outcomes['n_new_poor'].div(
- outcomes['tot_pop']).multiply(100))
-
- # Move years_in_poverty column to the end of the data frame
- outcomes = outcomes[[c for c in outcomes if c not in [
- 'years_in_poverty']] + ['years_in_poverty']]
-
- return outcomes
-
-
-def get_spatial_outcomes(outcomes: pd.DataFrame, country: str, outcomes_of_interest: list = [], aggregation: str = 'median') -> gpd.GeoDataFrame:
- '''Connect outcomes with spatial data.
-
- Args:
- outcomes (pd.DataFrame): Outcomes data frame.
- country (str, optional): Country name.
- outcomes_of_interest (list, optional): List of outcomes of interest. Defaults to [].
- aggregation (str, optional): Aggregation method. Defaults to 'median'.
-
- Returns:
- gpd.GeoDataFrame: Spatial outcomes.
- '''
-
- if aggregation not in ['mean', 'median']:
- raise ValueError('Aggregation must be either mean or median')
-
- if country == 'Saint Lucia':
- column = 'NAME_1'
- gdf = gpd.read_file(
- f'../data/raw/shapefiles/{country}/gadm36_LCA_shp/gadm36_LCA_1.shp')
-
- gdf['NAME_1'].replace(
- {'Soufrière': 'Soufriere', 'Vieux Fort': 'Vieuxfort'}, inplace=True)
-
- # Merge Anse-la-Raye and Canaries into a single geometry
- geometry = gdf[gdf['NAME_1'].isin(
- ['Anse-la-Raye', 'Canaries'])].unary_union
-
- # Add it to the dataframe
- gdf.loc[len(gdf)] = [None, None, 'LCA.11_1', 'Anse-La-Raye & Canaries',
- None, None, None, None, None, None, geometry]
- gdf = gdf[gdf['NAME_1'].isin(outcomes['region'].unique())]
-
- elif country == 'Dominica':
- column = 'NAME'
- gdf = gpd.read_file(
- '../../data/raw/shapefiles/Dominica/dma_admn_adm1_py_s1_dominode_v2.shp')
-
- elif country == 'Nigeria':
- column = 'shapeName'
- gdf = gpd.read_file(
- '../../data/raw/shapefiles/Nigeria/geoBoundaries-NGA-ADM1-all/geoBoundaries-NGA-ADM1.shp')
-
- else:
- raise ValueError('Country not supported')
-
- if len(outcomes_of_interest) == 0:
- outcomes_of_interest = [
- 'tot_asset_loss',
- 'region_pml',
- 'tot_exposed_asset',
- 'tot_consum_loss_npv',
- 'n_aff_people',
- 'n_new_poor',
- 'new_poverty_gap_all',
- 'annual_avg_consum_loss',
- 'annual_avg_consum_loss_pct',
- 'n_new_poor_increase_pp',
- 'n_poor_ratio',
- 'r']
-
- # Aggregate outcomes
- if aggregation == 'mean':
- aggregated = outcomes[['region'] +
- outcomes_of_interest].groupby('region').mean()
- elif aggregation == 'median':
- aggregated = outcomes[['region'] +
- outcomes_of_interest].groupby('region').median()
- else:
- raise ValueError('Aggregation must be either mean or median')
-
- # Merge with the shapefile
- gdf = pd.merge(gdf, aggregated, left_on=column, right_index=True)
- gdf.reset_index(inplace=True, drop=True)
- return gdf
-
-
-def get_policy_effectiveness_tab(outcomes: pd.DataFrame) -> pd.DataFrame:
- '''Get the policy effectiveness table.
-
- Effectiveness here is how effective the policy is in respect to:
- - reducing the number of new poor;
- - reducing the average consumption loss.
-
- Args:
- outcomes (pd.DataFrame): Outcomes.
-
- Returns:
- pd.DataFrame: Policy effectiveness table.
- '''
- policy_name_mapper = {'all+0': 'None',
- 'all+10': '10% to all',
- 'all+30': '30% to all',
- 'all+50': '50% to all',
- 'all+100': '100% to all',
- 'poor+0': 'None',
- 'poor+10': '10% to poor',
- 'poor+30': '30% to poor',
- 'poor+50': '50% to poor',
- 'poor+100': '100% to poor',
- 'poor_near_poor1.25+0': 'None',
- 'poor_near_poor1.25+10': '10% to poor and near poor (1.25)',
- 'poor_near_poor1.25+30': '30% to poor and near poor (1.25)',
- 'poor_near_poor1.25+50': '50% to poor and near poor (1.25)',
- 'poor_near_poor1.25+100': '100% to poor and near poor (1.25)',
- 'poor_near_poor2.0+0': 'None',
- 'poor_near_poor2.0+10': '10% to poor and near poor (2.0)',
- 'poor_near_poor2.0+30': '30% to poor and near poor (2.0)',
- 'poor_near_poor2.0+50': '50% to poor and near poor (2.0)',
- 'poor_near_poor2.0+100': '100% to poor and near poor (2.0)'}
- df = outcomes.copy()
- df['my_policy'] = df['my_policy'].replace(policy_name_mapper)
- df['my_policy'] = pd.Categorical(df['my_policy'], categories=['None', '10% to all', '30% to all', '50% to all', '100% to all',
- '10% to poor', '30% to poor', '50% to poor', '100% to poor',
- '10% to poor and near poor (1.25)', '30% to poor and near poor (1.25)', '50% to poor and near poor (1.25)', '100% to poor and near poor (1.25)',
- '10% to poor and near poor (2.0)', '30% to poor and near poor (2.0)', '50% to poor and near poor (2.0)', '100% to poor and near poor (2.0)'], ordered=True)
- df.rename(columns={'my_policy': 'Policy',
- 'region': 'Region'}, inplace=True)
- df.rename(columns={'annual_average_consumption_loss_pct': 'Annual average consumption loss (%)',
- 'n_new_poor': 'Number of new poor'},
- inplace=True)
- df['Policy ID'] = df['Policy'].cat.codes
- return df
-
-
-def get_weeks_in_poverty_tab(outcomes: pd.DataFrame) -> pd.DataFrame:
- '''Get the average across scenarios number of weeks in poverty for each region.
-
- Args:
- outcomes (pd.DataFrame): Outcomes.
-
- Returns:
- pd.DataFrame: Average number of weeks in poverty for each region.
- '''
- # Specify the regions
- regions = ['Anse-La-Raye & Canaries', 'Castries', 'Choiseul',
- 'Dennery', 'Gros Islet', 'Laborie', 'Micoud', 'Soufriere', 'Vieuxfort']
- regions = outcomes['region'].unique()
-
- # Keep track of the averages
- region_average = {}
-
- # Get the number of scenarios
- n_scenarios = outcomes['scenario'].unique().size
-
- # Get the keys
- column_name = 'years_in_poverty'
- all_keys = outcomes[column_name][0].keys()
-
- # Iterate through the regions
- for region in regions:
- # Subset the outcomes for a specific region
- df = outcomes[outcomes['region'] == region]
-
- # Get the dictionaries from the column
- dicts = df[column_name].tolist()
-
- # Initialize the sums
- sums = dict(zip(all_keys, [0] * len(all_keys)))
-
- # Iterate through the dictionaries and update the sums
- for d in dicts:
- for key in all_keys:
- if key in d:
- sums[key] += d[key]
- else:
- sums[key] += 0
-
- # Calculate the average
- region_average[region] = {
- key: sums[key] / n_scenarios for key in all_keys}
-
- # Convert the dictionary to a dataframe
- result = pd.DataFrame(region_average).T
- result.index.name = 'Region'
- result.columns = [i for i in range(0, len(all_keys))]
- # result.columns = [int(x) if int(x) < len(
- # all_keys) else f'>{len(all_keys)}' for x in range(1, len(all_keys) + 1)]
- return result
-
-
-def get_average_weighted_vulnerability(outcomes: pd.DataFrame, quintile: bool) -> pd.DataFrame:
- '''Get the average weighted vulnerability for each region.
-
- Args:
- outcomes (pd.DataFrame): Outcomes.
- quintile (bool): Whether to calculate the average weighted vulnerability by quintile or decile.
-
- Returns:
- pd.DataFrame: Average weighted vulnerability for each region.
- '''
- # Specify the regions
- regions = ['Anse-La-Raye & Canaries', 'Castries', 'Choiseul',
- 'Dennery', 'Gros Islet', 'Laborie', 'Micoud', 'Soufriere', 'Vieuxfort']
-
- # Keep track of the averages
- region_average = {}
-
- # Get the number of scenarios
- n_scenarios = outcomes['scenario'].unique().size
-
- if quintile:
- column_name = 'weighted_vuln_quint'
- all_keys = [1, 2, 3, 4, 5]
- else:
- column_name = 'weighted_vuln_dec'
- all_keys = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
-
- # Iterate through the regions
- for region in regions:
- # Subset the outcomes for a specific region
- df = outcomes[outcomes['region'] == region]
-
- # Get the dictionaries from the column
- dicts = df[column_name].tolist()
-
- # Initialize the sums
- sums = dict(zip(all_keys, [0] * len(all_keys)))
-
- # Iterate through the dictionaries and update the sums
- for d in dicts:
- for key in all_keys:
- if key in d:
- sums[key] += d[key]
- else:
- sums[key] += 0
-
- # Calculate the average
- region_average[region] = {
- key: sums[key] / n_scenarios for key in all_keys}
-
- # Convert the dictionary to a dataframe
- result = pd.DataFrame(region_average).T
-
- # Rename the index and columns
- result.index.name = 'region'
- if quintile:
- result.columns.name = 'Quintile'
- else:
- result.columns.name = 'Decile'
- return result
-
-
-def calculate_resilience(affected_households: pd.DataFrame, tot_wellbeing_loss: float) -> float:
- '''Calculate socio-economic resilience of affected households.
-
- Socio-economic resilience is a ratio of asset loss to consumption loss.
-
- Args:
- affected_households (pd.DataFrame): Affected households.
- tot_wellbeing_loss (float): Total wellbeing loss.
-
- Returns:
- float: Socio-economic resilience
- '''
- total_consumption_loss = (
- affected_households[['consumption_loss_NPV', 'popwgt']].prod(axis=1)).sum()
-
- total_asset_damage = (
- affected_households[['keff', 'v', 'popwgt']].prod(axis=1)).sum()
-
- if total_consumption_loss == 0:
- r = np.nan
-
- else:
- r = total_asset_damage / total_consumption_loss
- # r = total_asset_damage / tot_wellbeing_loss
-
- return r
-
-
-def split_policies(outcomes: pd.DataFrame) -> tuple:
- # TODO: Make the function more flexible and allow for different top ups and target groups
- # Split ASP policies
- asp = outcomes[outcomes['current_policy'].str.contains('asp')].copy()
- asp[['target_group', 'top_up']] = asp['current_policy'].str.split(
- '+', expand=True)
- asp['target_group'] = asp['target_group'].str.split(':', expand=True)[1]
-
- # Make top_up a categorical variable to ensure it is ordered correctly
- asp['top_up'] = pd.Categorical(asp['top_up'], categories=['0', '10', '50'])
- asp['target_group'] = pd.Categorical(asp['target_group'], categories=[
- 'poor_near_poor2.0', 'all'])
-
- # Append None policy to ASP
- none = outcomes[outcomes['current_policy'] == 'none'].copy()
- none['target_group'] = 'none'
- none['top_up'] = 'none'
- none['current_policy'] = 'none'
- asp = pd.concat([asp, none])
-
- # Split retrofit policies
- retrofit = outcomes[outcomes['current_policy'].str.contains(
- 'retrofit')].copy()
- retrofit[['target_group', 'houses_pct']
- ] = retrofit['current_policy'].str.split('+', expand=True)
- retrofit['target_group'] = retrofit['target_group'].str.split(':', expand=True)[
- 1]
- retrofit = pd.concat([retrofit, none])
- return asp, retrofit
diff --git a/unbreakable/analysis/calculator.py b/unbreakable/analysis/calculator.py
deleted file mode 100644
index 25e3c88..0000000
--- a/unbreakable/analysis/calculator.py
+++ /dev/null
@@ -1,281 +0,0 @@
-import pandas as pd
-import numpy as np
-import yaml
-
-
-def calculate_outcomes(households: pd.DataFrame, tot_exposed_asset: float, expected_loss_frac: float, region_pml: float, years_to_recover: int, welfare: float) -> dict:
- outcomes = {}
-
- # Get total population and poverty line
- tot_pop = households['wgt'].sum()
- pov_line_adjust = households['poverty_line_adjusted'].values[0]
-
- # Subset affected households
- aff_households = households[households['is_affected'] == True]
-
- # Write already precomputed outcomes
- outcomes['return_period'] = households['return_period'].iloc[0]
- outcomes['tot_pop'] = tot_pop
- outcomes['tot_households'] = households.shape[0]
- outcomes['n_aff_people'] = aff_households['wgt'].sum()
- outcomes['n_aff_households'] = aff_households.shape[0]
-
- try:
- outcomes['n_retrofitted'] = households[households['retrofitted']
- == True]['wgt'].sum()
- outcomes['n_retrofitted_hh'] = households[households['retrofitted']
- == True].shape[0]
- outcomes['n_aff_retrofitted'] = aff_households[aff_households['retrofitted']
- == True]['wgt'].sum()
- outcomes['n_aff_retrofitted_hh'] = aff_households[aff_households['retrofitted'] == True].shape[0]
-
- except:
- outcomes['n_retrofitted_ppl'] = 0
- outcomes['n_retrofitted_hh'] = 0
- outcomes['n_aff_retrofitted_ppl'] = 0
- outcomes['n_aff_retrofitted_hh'] = 0
-
- outcomes['tot_asset_surv'] = households['tot_asset_surv'].iloc[0]
- outcomes['tot_exposed_asset'] = tot_exposed_asset
- outcomes['tot_asset_loss'] = aff_households[[
- 'keff', 'v', 'wgt']].prod(axis=1).sum()
- outcomes['expected_loss_frac'] = expected_loss_frac
- outcomes['region_pml'] = region_pml
- outcomes['annual_avg_consum'] = weighted_mean(households, 'exp', 'wgt')
- outcomes['pov_line_adjust'] = households['poverty_line_adjusted'].iloc[0]
- outcomes['mean_recovery_rate'] = aff_households['recovery_rate'].mean()
- outcomes['tot_consum_loss_npv'] = weighted_sum(
- aff_households, 'consumption_loss_npv', 'wgt')
-
- # Calculate model outcomes
- n_poor_initial, n_new_poor, n_poor_affected, poor_initial, new_poor = find_poor(
- households, pov_line_adjust, years_to_recover)
-
- years_in_poverty = get_people_by_years_in_poverty(new_poor)
-
- initial_poverty_gap, new_poverty_gap_initial, new_poverty_gap_all = calculate_poverty_gap(
- poor_initial, new_poor, pov_line_adjust, years_to_recover)
-
- annual_average_consumption_loss, annual_average_consumption_loss_pct = calculate_average_annual_consumption_loss(
- aff_households, years_to_recover)
-
- tot_consum_equiv_loss = - aff_households['wellbeing'].div(welfare).multiply(
- aff_households['wgt']).sum()
-
- r = calculate_resilience(aff_households, tot_consum_equiv_loss)
-
- outcomes['n_poor_initial'] = n_poor_initial
- outcomes['n_poor_affected'] = n_poor_affected
- outcomes['n_new_poor'] = n_new_poor
- outcomes['initial_poverty_gap'] = initial_poverty_gap
- outcomes['new_poverty_gap_initial'] = new_poverty_gap_initial
- outcomes['new_poverty_gap_all'] = new_poverty_gap_all
- outcomes['annual_avg_consum_loss'] = annual_average_consumption_loss
- outcomes['annual_avg_consum_loss_pct'] = annual_average_consumption_loss_pct
- outcomes['r'] = r
- outcomes['years_in_poverty'] = years_in_poverty
-
- # Save outcome names in a yaml file to pick up in preprocessing
- with open('analysis/outcomes.yaml', 'w') as f:
- yaml.dump(list(outcomes.keys()), f)
-
- return outcomes
-
-
-def find_poor(households: pd.DataFrame, pov_line: float, years_to_recover: int) -> tuple:
- '''Get the poor at the beginning of the simulation and the poor at the end of the simulation
-
- Args:
- households (pd.DataFrame): Households.
- pov_line (float): Poverty line.
- years_to_recover (int): Number of years cut-off parameter when calculating consumption loss.
-
- Returns:
- tuple: Number of poor at the beginning of the simulation, number of new poor at the end of the simulation, and the new poor dataframe
- '''
- # First, find the poor at the beginning of the simulation
- poor_initial = households[households['is_poor'] == True]
- n_poor_initial = round(poor_initial['wgt'].sum())
- n_poor_affected = round(
- poor_initial[poor_initial['is_affected'] == True]['wgt'].sum())
-
- # Second, find the new poor at the end of the simulation (`years_to_recover`)
- not_poor = households[households['is_poor'] == False]
- not_poor_affected = not_poor[not_poor['is_affected'] == True]
- x = not_poor_affected['exp'] - \
- not_poor_affected['consumption_loss_npv'] / years_to_recover
- new_poor = not_poor_affected.loc[x < pov_line, :]
- new_poor = new_poor.assign(is_poor=True)
- n_new_poor = round(new_poor['wgt'].sum())
-
- return n_poor_initial, n_new_poor, n_poor_affected, poor_initial, new_poor
-
-
-def get_people_by_years_in_poverty(affected_households: pd.DataFrame) -> dict:
- '''Get the number of people in poverty for each year in poverty.
-
- Args:
- affected_households (pd.DataFrame): Affected households
-
- Returns:
- dict: Number of people in poverty for each year in poverty
- '''
- affected_households = affected_households.assign(
- years_in_poverty=affected_households['weeks_in_poverty'] // 52)
- d = {}
- longest_years_in_poverty = 10
- for i in range(longest_years_in_poverty + 1):
- d[i] = round(affected_households[affected_households['years_in_poverty'] == i]
- ['wgt'].sum())
- return d
-
-
-def calculate_poverty_gap(poor_initial: pd.DataFrame, new_poor: pd.DataFrame, poverty_line: float, years_to_recover: int) -> tuple:
- '''Calculate the poverty gap at the beginning and at the end of the simulation.
-
- Args:
- poor_initial (pd.DataFrame): Poor at the beginning of the simulation
- new_poor (pd.DataFrame): New poor at the end of the simulation
- poverty_line (float): Poverty line
- years_to_recover (int): Number of years cut-off parameter when calculating consumption loss. Default is 10.
-
- Returns:
- tuple: Poverty gap at the beginning and at the end of the simulation
-
- Raises:
- Exception: If the index is duplicated
- Exception: If the poverty gap is greater than 1
- '''
- average_expenditure_poor_initial = (
- poor_initial['exp'] * poor_initial['wgt']).sum() / poor_initial['wgt'].sum()
-
- # assert poverty_line > average_expenditure_poor_initial, 'Poverty line cannot be less than average expenditure of the poor'
-
- initial_poverty_gap = (
- poverty_line - average_expenditure_poor_initial) / poverty_line
-
- # Combine the poor at the beginning of the simulation and the new poor at the end of the simulation
- all_poor = pd.concat([poor_initial, new_poor])
-
- # Expenditure of both were affected by the disaster
- all_poor = all_poor.assign(
- exp=all_poor['exp'] - all_poor['consumption_loss_npv'] / years_to_recover)
-
- # Now, get the average expenditure of the poor at the end of the simulation
- average_expenditure_poor_all = (
- all_poor['exp'] * all_poor['wgt']).sum() / all_poor['wgt'].sum()
-
- # Calculate the poverty gap at the end of the simulation
- new_poverty_gap_all = (
- poverty_line - average_expenditure_poor_all) / poverty_line
-
- # However, we also want to know the poverty gap for old poor
- poor_initial = poor_initial.assign(
- exp=poor_initial['exp'] - poor_initial['consumption_loss_npv'] / years_to_recover)
-
- average_expenditure_poor_initial = (
- poor_initial['exp'] * poor_initial['wgt']).sum() / poor_initial['wgt'].sum()
-
- new_poverty_gap_initial = (
- poverty_line - average_expenditure_poor_initial) / poverty_line
-
- # Poverty gap cannot be greater than 1
- if initial_poverty_gap > 1 or new_poverty_gap_initial > 1 or new_poverty_gap_all > 1:
- raise Exception('Poverty gap cannot be greater than 1')
-
- return initial_poverty_gap, new_poverty_gap_initial, new_poverty_gap_all
-
-
-def calculate_average_annual_consumption_loss(affected_households: pd.DataFrame, years_to_recover: int) -> tuple:
- '''Get the average annual consumption loss and the average annual consumption loss as a percentage of average annual consumption.
-
- Args:
- affected_households (pd.DataFrame): Affected households.
- years_to_recover (int): Number of years cut-off parameter when calculating consumption loss. Default is 10.
-
- Returns:
- tuple: Average annual consumption loss and average annual consumption loss as a percentage of average annual consumption
-
- Raises:
- Exception: If the average annual consumption loss is greater than 1
- '''
-
- if len(affected_households) == 0:
- return np.nan, np.nan
-
- # Annual consumption loss
- annual_consumption_loss = (
- affected_households['consumption_loss_npv'].div(years_to_recover).multiply(affected_households['wgt'])).sum()
-
- # Weighted average
- annual_average_consumption_loss = annual_consumption_loss / \
- affected_households['wgt'].sum()
-
- annual_average_consumption_loss_pct = (affected_households['consumption_loss_npv']
- .div(years_to_recover)
- .div(affected_households['exp'])
- .multiply(affected_households['wgt']).sum())\
- / affected_households['wgt'].sum()
-
- if annual_average_consumption_loss_pct > 1:
- raise Exception(
- 'Annual average consumption loss pct is greater than 1')
-
- return annual_average_consumption_loss, annual_average_consumption_loss_pct
-
-
-def calculate_resilience(affected_households: pd.DataFrame, tot_consum_equiv_loss: float) -> float:
- '''Calculate socio-economic resilience of affected households.
-
- Socio-economic resilience is a ratio of asset loss to consumption loss.
-
- Args:
- affected_households (pd.DataFrame): Affected households.
- tot_consum_equiv_loss (float): Total consumption equivalent loss.
-
- Returns:
- float: Socio-economic resilience
- '''
- # TODO: Test resilience values, it should not go above, e.g., 10
- # total_consumption_loss = (
- # affected_households[['consumption_loss_NPV', 'wgt']].prod(axis=1)).sum()
-
- total_asset_damage = (
- affected_households[['keff', 'v', 'wgt']].prod(axis=1)).sum()
-
- # if total_consumption_loss == 0:
- # r = np.nan
-
- # else:
- # r = total_asset_damage / total_consumption_loss
- r = total_asset_damage / tot_consum_equiv_loss
-
- return r
-
-
-def weighted_sum(df: pd.DataFrame, col: str, wgt: str) -> float:
- '''Calculate the weighted sum of a column in a dataframe.
-
- Args:
- df (pd.DataFrame): Dataframe.
- col (str): Column name.
- wgt (str): Weight column name.
-
- Returns:
- float: Weighted sum of a column in a dataframe.
- '''
- return (df[col] * df[wgt]).sum()
-
-
-def weighted_mean(df: pd.DataFrame, col: str, wgt: str) -> float:
- '''Calculate the weighted mean of a column in a dataframe.
-
- Args:
- df (pd.DataFrame): Dataframe.
- col (str): Column name.
- wgt (str): Weight column name.
-
- Returns:
- float: Weighted mean of a column in a dataframe.
- '''
- return weighted_sum(df, col, wgt) / df[wgt].sum()
diff --git a/unbreakable/analysis/distributional_metrics.py b/unbreakable/analysis/distributional_metrics.py
new file mode 100644
index 0000000..9e15a0d
--- /dev/null
+++ b/unbreakable/analysis/distributional_metrics.py
@@ -0,0 +1,168 @@
+import pandas as pd
+import numpy as np
+from typing import Dict, List, Any
+from functools import partial
+from unbreakable.analysis.economic_metrics import (
+ calculate_average_annual_consumption_loss,
+)
+from unbreakable.analysis.resilience_metrics import calculate_socioeconomic_resilience
+
+
+def calculate_distributional_impacts(
+ households: pd.DataFrame,
+ max_years: int,
+ socioeconomic_attributes: List[str],
+ baseline_avg_annual_consumption_loss_pct: float,
+ baseline_resilience: Dict[str, float],
+) -> Dict[str, float]:
+ """
+ Calculate distributional impacts across different socioeconomic groups.
+
+ This function analyzes the impact of disasters on various socioeconomic groups
+ by calculating metrics such as consumption loss and resilience for each group.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data.
+ max_years (int): Maximum number of years for calculating annualized consumption loss.
+ socioeconomic_attributes (List[str]): List of column names representing socioeconomic attributes.
+ baseline_avg_annual_consumption_loss_pct (float): Baseline average annual consumption loss percentage.
+ baseline_resilience (Dict[str, float]): Baseline resilience metrics.
+
+ Returns:
+ Dict[str, float]: A dictionary containing calculated impact metrics for each socioeconomic group.
+ """
+ outcomes = {}
+ # Filter for affected households
+ affected_households = households[households["ever_affected"]]
+
+ # Iterate through each socioeconomic attribute
+ for column in socioeconomic_attributes:
+ # Get unique, non-null values for the current attribute
+ group_values = households[column].dropna().unique()
+
+ # Calculate impacts for each group within the current attribute
+ for group_value in group_values:
+ # Filter affected households for the current group
+ group_households = affected_households[
+ affected_households[column] == group_value
+ ]
+
+ if group_households.empty:
+ # Handle empty groups by passing empty DataFrame and default values
+ group_outcomes = calculate_group_outcomes(
+ column,
+ group_value,
+ pd.DataFrame(),
+ affected_households,
+ 0.0,
+ 0.0,
+ {"consumption_based": 0.0, "wellbeing_based": 0.0},
+ baseline_avg_annual_consumption_loss_pct,
+ baseline_resilience,
+ )
+ else:
+ # Calculate metrics for non-empty groups
+ avg_consumption_loss, avg_consumption_loss_pct = (
+ calculate_average_annual_consumption_loss(
+ group_households, max_years
+ )
+ )
+ resilience = calculate_socioeconomic_resilience(group_households)
+
+ group_outcomes = calculate_group_outcomes(
+ column,
+ group_value,
+ group_households,
+ affected_households,
+ avg_consumption_loss,
+ avg_consumption_loss_pct,
+ resilience,
+ baseline_avg_annual_consumption_loss_pct,
+ baseline_resilience,
+ )
+
+ outcomes.update(group_outcomes)
+
+ return outcomes
+
+
+def calculate_group_outcomes(
+ column: str,
+ group_value: Any,
+ group_households: pd.DataFrame,
+ affected_households: pd.DataFrame,
+ average_consumption_loss: float,
+ average_consumption_loss_pct: float,
+ resilience: Dict[str, float],
+ baseline_avg_annual_consumption_loss_pct: float,
+ baseline_resilience: Dict[str, float],
+) -> Dict[str, float]:
+ """
+ Calculate impact outcomes for a specific socioeconomic group.
+
+ This function computes various impact metrics for a given socioeconomic group,
+ including consumption loss, reconstruction rates, and resilience measures.
+
+ Args:
+ column (str): Name of the socioeconomic attribute.
+ group_value (Any): The specific value of the socioeconomic attribute for this group.
+ group_households (pd.DataFrame): DataFrame containing data for households in this group.
+ affected_households (pd.DataFrame): DataFrame containing data for all affected households.
+ average_consumption_loss (float): Average annual consumption loss for this group.
+ average_consumption_loss_pct (float): Average consumption loss percentage for this group.
+ resilience (Dict[str, float]): Resilience metrics for this group.
+ baseline_avg_annual_consumption_loss_pct (float): Baseline average annual consumption loss percentage.
+ baseline_resilience (Dict[str, float]): Baseline resilience metrics.
+
+ Returns:
+ Dict[str, float]: A dictionary containing calculated impact metrics for the specific group.
+ """
+ if group_households.empty:
+ return {
+ # f"annual_average_consumption_loss_{column}_{group_value}": None,
+ f"annual_average_consumption_loss_pct_{column}_{group_value}": None,
+ f"average_consumption_loss_pct_difference_{column}_{group_value}": None,
+ # f"average_reconstruction_rate_{column}_{group_value}": None,
+ f"average_reconstruction_rate_difference_{column}_{group_value}": None,
+ # f"r_consumption_based_{column}_{group_value}": None,
+ f"r_consumption_based_difference_{column}_{group_value}": None,
+ # f"r_wellbeing_based_{column}_{group_value}": None,
+ f"r_wellbeing_based_difference_{column}_{group_value}": None,
+ }
+
+ return {
+ # f"annual_average_consumption_loss_{column}_{group_value}": average_consumption_loss,
+ f"annual_average_consumption_loss_pct_{column}_{group_value}": average_consumption_loss_pct,
+ f"average_consumption_loss_pct_difference_{column}_{group_value}": (
+ (average_consumption_loss_pct - baseline_avg_annual_consumption_loss_pct)
+ / baseline_avg_annual_consumption_loss_pct
+ if baseline_avg_annual_consumption_loss_pct != 0
+ else 0.0
+ ),
+ f"average_reconstruction_rate_{column}_{group_value}": group_households[
+ "reconstruction_rate"
+ ].mean(),
+ f"average_reconstruction_rate_difference_{column}_{group_value}": (
+ (
+ group_households["reconstruction_rate"].mean()
+ - affected_households["reconstruction_rate"].mean()
+ )
+ / affected_households["reconstruction_rate"].mean()
+ if affected_households["reconstruction_rate"].mean() != 0
+ else 0.0
+ ),
+ f"r_consumption_based_{column}_{group_value}": resilience["consumption_based"],
+ f"r_consumption_based_difference_{column}_{group_value}": (
+ (resilience["consumption_based"] - baseline_resilience["consumption_based"])
+ / baseline_resilience["consumption_based"]
+ if baseline_resilience["consumption_based"] != 0
+ else 0.0
+ ),
+ f"r_wellbeing_based_{column}_{group_value}": resilience["wellbeing_based"],
+ f"r_wellbeing_based_difference_{column}_{group_value}": (
+ (resilience["wellbeing_based"] - baseline_resilience["wellbeing_based"])
+ / baseline_resilience["wellbeing_based"]
+ if baseline_resilience["wellbeing_based"] != 0
+ else 0.0
+ ),
+ }
diff --git a/unbreakable/analysis/economic_metrics.py b/unbreakable/analysis/economic_metrics.py
new file mode 100644
index 0000000..8650b82
--- /dev/null
+++ b/unbreakable/analysis/economic_metrics.py
@@ -0,0 +1,56 @@
+import pandas as pd
+from typing import Tuple
+
+
+def calculate_average_annual_consumption_loss(
+ affected_households: pd.DataFrame, max_years: int
+) -> Tuple[float, float]:
+ """
+ Calculate the average annual consumption loss and its percentage of average annual consumption.
+
+ Args:
+ affected_households (pd.DataFrame): Affected households data. Must include columns:
+ - consumption_loss_npv: Net present value of consumption loss
+ - household_weight: Household weight
+ - exp: Annual consumption (expenditure)
+ max_years (int): Number of years cut-off parameter for calculating consumption loss.
+
+ Returns:
+ Tuple[float, float]:
+ - Average annual consumption loss
+ - Average annual consumption loss as a percentage of average annual consumption
+
+ Raises:
+ ValueError: If the average annual consumption loss percentage is greater than 100%
+ ValueError: If the DataFrame is empty
+ """
+ if affected_households.empty:
+ raise ValueError("The affected_households DataFrame is empty.")
+
+ # Calculate annual consumption loss
+ annual_consumption_loss = (
+ affected_households["consumption_loss_npv"]
+ .div(max_years)
+ .mul(affected_households["household_weight"])
+ .sum()
+ )
+
+ # Calculate weighted average annual consumption loss
+ total_weight = affected_households["household_weight"].sum()
+ annual_average_consumption_loss = annual_consumption_loss / total_weight
+
+ # Calculate percentage of average annual consumption loss
+ annual_average_consumption_loss_pct = (
+ affected_households["consumption_loss_npv"]
+ .div(max_years)
+ .div(affected_households["exp"])
+ .mul(affected_households["household_weight"])
+ .sum()
+ ) / total_weight
+
+ if annual_average_consumption_loss_pct > 1:
+ raise ValueError(
+ "Annual average consumption loss percentage is greater than 100%"
+ )
+
+ return annual_average_consumption_loss, annual_average_consumption_loss_pct
diff --git a/unbreakable/analysis/metric_calculator.py b/unbreakable/analysis/metric_calculator.py
new file mode 100644
index 0000000..a325ee7
--- /dev/null
+++ b/unbreakable/analysis/metric_calculator.py
@@ -0,0 +1,106 @@
+import pandas as pd
+from typing import Dict, Any
+import json
+import numpy as np
+
+from unbreakable.analysis.poverty_metrics import (
+ analyze_poor_population,
+ analyze_poverty_duration,
+ calculate_poverty_gaps,
+)
+from unbreakable.analysis.resilience_metrics import calculate_socioeconomic_resilience
+from unbreakable.analysis.economic_metrics import (
+ calculate_average_annual_consumption_loss,
+)
+from unbreakable.analysis.distributional_metrics import (
+ calculate_distributional_impacts,
+)
+
+
+def calculate_metrics(
+ households: pd.DataFrame, max_years: int, analysis_params: Dict[str, Any]
+) -> Dict[str, float]:
+ """
+ Calculate various metrics across affected households.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data.
+ max_years (int): Number of years for calculating annualized consumption loss.
+ analysis_params (Dict[str, Any]): Dictionary containing analysis parameters.
+
+ Returns:
+ Dict[str, float]: A dictionary containing calculated metrics.
+ """
+ affected_households = households[households["ever_affected"]].copy()
+
+ # Calculate years to recover
+ affected_households["years_to_recover"] = np.round(
+ np.log(1 / 0.05) / affected_households["reconstruction_rate"]
+ )
+
+ avg_years_to_recover = affected_households["years_to_recover"].mean()
+ avg_dwelling_vulnerability = affected_households["v"].mean()
+
+ # Calculate poverty metrics
+ (
+ initial_poor_count,
+ new_poor_count,
+ affected_poor_count,
+ initial_poor_df,
+ new_poor_df,
+ ) = analyze_poor_population(households, max_years)
+
+ poverty_duration = analyze_poverty_duration(affected_households, max_years)
+
+ initial_poverty_gap, updated_initial_poverty_gap, overall_poverty_gap = (
+ calculate_poverty_gaps(initial_poor_df, new_poor_df, max_years)
+ )
+
+ # Calculate resilience metrics
+ resilience = calculate_socioeconomic_resilience(affected_households)
+
+ # Calculate economic metrics
+ avg_annual_consumption_loss, avg_annual_consumption_loss_pct = (
+ calculate_average_annual_consumption_loss(affected_households, max_years)
+ )
+
+ # Compile results
+ results = {
+ "households_count": len(households),
+ "affected_households_count": len(affected_households),
+ "people_count": households["household_weight"].sum(),
+ "affected_people_count": affected_households["household_weight"].sum(),
+ "initial_poor_count": initial_poor_count,
+ "new_poor_count": new_poor_count,
+ "affected_poor_count": affected_poor_count,
+ "initial_poverty_gap": initial_poverty_gap,
+ "updated_initial_poverty_gap": updated_initial_poverty_gap,
+ "overall_poverty_gap": overall_poverty_gap,
+ "resilience_consumption_based": resilience["consumption_based"],
+ "resilience_wellbeing_based": resilience["wellbeing_based"],
+ "annual_average_consumption_loss": avg_annual_consumption_loss,
+ "annual_average_consumption_loss_pct": avg_annual_consumption_loss_pct,
+ "average_years_to_recover": avg_years_to_recover,
+ "average_dwelling_vulnerability": avg_dwelling_vulnerability,
+ **{
+ f"poverty_duration_{year}": count
+ for year, count in poverty_duration.items()
+ },
+ }
+
+ # Calculate distributional impacts if required
+ if analysis_params.get("distributional_impacts", False):
+ distributional_outcomes = calculate_distributional_impacts(
+ households,
+ max_years,
+ analysis_params.get("socioeconomic_attributes", []),
+ avg_annual_consumption_loss_pct,
+ resilience,
+ )
+ results.update(distributional_outcomes)
+
+ # Save results keys in a json file
+ with open("experiments/outcome_names_ordered.json", "w") as f:
+ json.dump(list(results.keys()), f)
+
+ return results
diff --git a/unbreakable/analysis/outcomes.yaml b/unbreakable/analysis/outcomes.yaml
deleted file mode 100644
index 6604855..0000000
--- a/unbreakable/analysis/outcomes.yaml
+++ /dev/null
@@ -1,28 +0,0 @@
-- return_period
-- tot_pop
-- tot_households
-- n_aff_people
-- n_aff_households
-- n_retrofitted_ppl
-- n_retrofitted_hh
-- n_aff_retrofitted_ppl
-- n_aff_retrofitted_hh
-- tot_asset_surv
-- tot_exposed_asset
-- tot_asset_loss
-- expected_loss_frac
-- region_pml
-- annual_avg_consum
-- pov_line_adjust
-- mean_recovery_rate
-- tot_consum_loss_npv
-- n_poor_initial
-- n_poor_affected
-- n_new_poor
-- initial_poverty_gap
-- new_poverty_gap_initial
-- new_poverty_gap_all
-- annual_avg_consum_loss
-- annual_avg_consum_loss_pct
-- r
-- years_in_poverty
diff --git a/unbreakable/analysis/poverty_metrics.py b/unbreakable/analysis/poverty_metrics.py
new file mode 100644
index 0000000..df5445a
--- /dev/null
+++ b/unbreakable/analysis/poverty_metrics.py
@@ -0,0 +1,193 @@
+import pandas as pd
+from typing import Dict
+
+
+def analyze_poor_population(
+ households: pd.DataFrame, max_years: int
+) -> tuple[int, int, int, pd.DataFrame, pd.DataFrame]:
+ """
+ Analyze and categorize poor population based on initial state and after-disaster effects.
+
+ This function identifies the initially poor population, the affected poor population,
+ and the newly poor population after considering disaster effects over a specified recovery period.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data.
+ max_years (int): Number of years for calculating annualized consumption loss.
+
+ Returns:
+ tuple[int, int, int, pd.DataFrame, pd.DataFrame]: A tuple containing:
+ - initial_poor_count: Number of initially poor households.
+ - new_poor_count: Number of newly poor households after disaster effects.
+ - affected_poor_count: Number of initially poor households affected by the disaster.
+ - initial_poor_df: DataFrame of initially poor households.
+ - new_poor_df: DataFrame of newly poor households.
+
+ Note:
+ The function assumes the presence of specific columns in the input DataFrame:
+ 'poverty_line', 'is_poor', 'household_weight', 'ever_affected', 'exp', 'consumption_loss_npv'.
+ """
+ poverty_line = households["poverty_line"].iloc[0]
+
+ # Identify initially poor households
+ initial_poor_df = households[households["is_poor"]]
+ initial_poor_count = round(initial_poor_df["household_weight"].sum())
+
+ # Identify affected poor households
+ affected_poor_df = initial_poor_df[initial_poor_df["ever_affected"]]
+ affected_poor_count = round(affected_poor_df["household_weight"].sum())
+
+ # Identify newly poor households
+ initially_not_poor_df = households[~households["is_poor"]]
+ affected_not_poor_df = initially_not_poor_df[initially_not_poor_df["ever_affected"]]
+
+ post_disaster_expenditure = (
+ affected_not_poor_df["exp"]
+ - affected_not_poor_df["consumption_loss_npv"] / max_years
+ )
+
+ # ! The poverty line is yearly and the expenditure is monthly
+ new_poor_df = affected_not_poor_df[
+ post_disaster_expenditure < (poverty_line / 12)
+ ].copy()
+ new_poor_df["is_poor"] = True
+ new_poor_count = round(new_poor_df["household_weight"].sum())
+
+ return (
+ initial_poor_count,
+ new_poor_count,
+ affected_poor_count,
+ initial_poor_df,
+ new_poor_df,
+ )
+
+
+def analyze_poverty_duration(
+ households: pd.DataFrame, max_years: int
+) -> Dict[int, int]:
+ """
+ Analyze the duration of poverty for affected households.
+
+ This function calculates the number of people experiencing poverty for different
+ durations, up to a specified maximum number of years.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing affected household data.
+ Must include 'weeks_in_poverty' and 'wgt' (weight) columns.
+ max_years (int, optional): Maximum number of years to consider. Defaults to 10.
+
+ Returns:
+ Dict[int, int]: A dictionary where keys are years in poverty (0 to max_years),
+ and values are the number of people experiencing poverty for that duration.
+
+ Note:
+ The function assumes that 'weeks_in_poverty' and 'household_weight' columns exist in the input DataFrame.
+ """
+ # Calculate years in poverty from weeks
+ households = households.copy()
+ households["years_in_poverty"] = households["weeks_in_poverty"] // 52
+
+ # Initialize dictionary with zeros for all year counts
+ poverty_duration_counts = {year: 0 for year in range(max_years + 1)}
+
+ # Group by years in poverty and sum weights
+ grouped_data = (
+ households.groupby("years_in_poverty")["household_weight"]
+ .sum()
+ .round()
+ .astype(int)
+ )
+
+ # Update dictionary with actual counts, capped at max_years
+ poverty_duration_counts.update(grouped_data[grouped_data.index <= max_years])
+
+ return poverty_duration_counts
+
+
+# TODO: Review how the poverty gaps are calculated
+
+
+def calculate_poverty_gaps(
+ initial_poor: pd.DataFrame, new_poor: pd.DataFrame, max_years: int = 10
+) -> tuple[float, float, float]:
+ """
+ Calculate the poverty gaps at the beginning and end of the simulation.
+ This function computes three poverty gaps:
+ 1. Initial poverty gap
+ 2. Updated poverty gap for initially poor population
+ 3. Overall poverty gap including newly poor population
+
+ Args:
+ initial_poor (pd.DataFrame): DataFrame of initially poor population.
+ new_poor (pd.DataFrame): DataFrame of newly poor population.
+ max_years (int): Number of years for calculating annualized consumption loss. Defaults to 10.
+
+ Returns:
+ tuple[float, float, float]: A tuple containing:
+ - initial_poverty_gap: Poverty gap at the beginning of the simulation.
+ - updated_initial_poverty_gap: Updated poverty gap for initially poor population.
+ - overall_poverty_gap: Poverty gap including both initial and newly poor populations.
+
+ Raises:
+ ValueError: If any calculated poverty gap is greater than 1.
+ """
+
+ def calculate_average_expenditure(df: pd.DataFrame) -> float:
+ if df.empty:
+ return 0
+ return (df["exp"] * df["household_weight"]).sum() / df["household_weight"].sum()
+
+ def calculate_poverty_gap(average_expenditure: float, poverty_line: float) -> float:
+ if average_expenditure >= poverty_line:
+ return 0
+ return (poverty_line - average_expenditure) / poverty_line
+
+ # Handle case when initial_poor is empty
+ if initial_poor.empty:
+ return 0, 0, 0 if new_poor.empty else 1
+
+ poverty_line = initial_poor["poverty_line"].iloc[0]
+ initial_poor = initial_poor.copy()
+ new_poor = new_poor.copy()
+
+ initial_avg_expenditure = calculate_average_expenditure(initial_poor)
+ initial_poverty_gap = calculate_poverty_gap(initial_avg_expenditure, poverty_line)
+
+ # Handle case when new_poor is empty
+ if new_poor.empty:
+ updated_initial_avg_expenditure = calculate_average_expenditure(
+ initial_poor.assign(
+ exp=lambda x: x["exp"] - x["consumption_loss_npv"] / max_years
+ )
+ )
+ updated_initial_poverty_gap = calculate_poverty_gap(
+ updated_initial_avg_expenditure, poverty_line
+ )
+ return (
+ initial_poverty_gap,
+ updated_initial_poverty_gap,
+ updated_initial_poverty_gap,
+ )
+
+ all_poor = pd.concat([initial_poor, new_poor])
+ all_poor["exp"] -= all_poor["consumption_loss_npv"] / max_years
+ overall_avg_expenditure = calculate_average_expenditure(all_poor)
+ overall_poverty_gap = calculate_poverty_gap(overall_avg_expenditure, poverty_line)
+
+ initial_poor["exp"] -= initial_poor["consumption_loss_npv"] / max_years
+ updated_initial_avg_expenditure = calculate_average_expenditure(initial_poor)
+ updated_initial_poverty_gap = calculate_poverty_gap(
+ updated_initial_avg_expenditure, poverty_line
+ )
+
+ if any(
+ gap > 1
+ for gap in [
+ initial_poverty_gap,
+ updated_initial_poverty_gap,
+ overall_poverty_gap,
+ ]
+ ):
+ raise ValueError("Poverty gap cannot be greater than 1")
+
+ return initial_poverty_gap, updated_initial_poverty_gap, overall_poverty_gap
diff --git a/unbreakable/analysis/resilience_metrics.py b/unbreakable/analysis/resilience_metrics.py
new file mode 100644
index 0000000..7a04818
--- /dev/null
+++ b/unbreakable/analysis/resilience_metrics.py
@@ -0,0 +1,69 @@
+import pandas as pd
+from typing import Dict
+
+
+def calculate_socioeconomic_resilience(
+ affected_households: pd.DataFrame,
+) -> Dict[str, float]:
+ """Calculate socio-economic resilience of affected households.
+
+ Socio-economic resilience is calculated using two methods:
+ 1. Consumption-based = Asset damage / consumption loss
+ 2. Wellbeing-based = Asset damage / consumption equivalent loss
+
+ Args:
+ affected_households (pd.DataFrame): Affected households.
+
+ Returns:
+ Dict[str, float]: Dictionary containing:
+ - consumption_based: Resilience based on consumption loss
+ - equivalent_based: Resilience based on consumption equivalent loss
+ """
+ total_asset_damage = (
+ affected_households[["keff", "v", "household_weight"]].prod(axis=1)
+ ).sum()
+
+ total_consumption_loss = (
+ affected_households[["consumption_loss_npv", "household_weight"]].prod(axis=1)
+ ).sum()
+
+ total_consumption_equivalent_loss = calculate_consumption_equivalent_loss(
+ affected_households
+ )
+
+ if total_consumption_loss == 0 or total_consumption_equivalent_loss == 0:
+ return {
+ "consumption_based": 0,
+ "wellbeing_based": 0,
+ }
+
+ else:
+ return {
+ "consumption_based": total_asset_damage / total_consumption_loss,
+ "wellbeing_based": total_asset_damage / total_consumption_equivalent_loss,
+ }
+
+
+def calculate_consumption_equivalent_loss(affected_households: pd.DataFrame) -> float:
+ """
+ Calculate the total consumption equivalent loss for affected households.
+
+ This function computes the sum of weighted wellbeing losses relative to welfare
+ across all affected households.
+
+ Args:
+ affected_households (pd.DataFrame): DataFrame containing affected households data.
+
+ Returns:
+ float: The total consumption equivalent loss, always returned as a positive number.
+
+ Note:
+ The function assumes that 'wellbeing_loss' is typically a negative value,
+ hence the negative sign in the calculation to return a positive loss.
+ """
+ total_consumption_equivalent_loss = -(
+ (affected_households["wellbeing_loss"] / affected_households["welfare"])
+ * affected_households["household_weight"]
+ ).sum()
+
+ return total_consumption_equivalent_loss
diff --git a/unbreakable/analysis/verifier.py b/unbreakable/analysis/verifier.py
deleted file mode 100644
index a6b7ebd..0000000
--- a/unbreakable/analysis/verifier.py
+++ /dev/null
@@ -1,139 +0,0 @@
-import os
-import pandas as pd
-from tqdm import tqdm
-
-
-def filter_and_save_consumption_data(country: str = 'Nigeria', return_period: int = 100, run_subset: bool = False, n_runs: int = 1, include_regions_of_interest: bool = False, regions_of_interest: list = None, save_results: bool = False):
- '''
- Filter and save the consumption recovery data for the specified country.
-
- Args:
- country (str): The country for which to load the data.
- return_period (int): The return period of the disaster.
- run_subset (bool): If True, only the first n_runs runs are included. If False, all runs are included.
- n_runs (int): The number of runs to include if run_subset is True.
- include_regions_of_interest (bool): If True, only data from regions are included. If False, data from all regions are included.
- regions_of_interest (list, optional): A list of regions of interest. Only used if include_regions_of_interest is True.
- save_results (bool): If True, the results are saved to a CSV file.
-
- Returns:
- dict: A dictionary with keys 'Conflict' and 'No Conflict', each containing a dictionary with 'region' and 'data'.
-
- Examples:
- # Load only 1 run
- run_subset = True
- n_runs = 1
-
- # Load only data from Oyo and Taraba
- include_regions_of_interest = True
- regions_of_interest = ['Oyo', 'Taraba']
-
- # Run the function
- results = filter_and_save_consumption_data(run_subset=run_subset, n_runs=n_runs, include_regions_of_interest=include_regions_of_interest, regions_of_interest=regions_of_interest, save_results=True)
- '''
- # Initialize the results dictionary
- results = {}
-
- # False - No Conflict, True - Conflict
- run_types = [False, True]
-
- # Loop through the two run types
- for c in run_types:
- # Set the path to the experiment data
- path = os.path.abspath(
- f'../../experiments/{country}/consumption_recovery/return_period={return_period}/conflict={c}/')
-
- # Get the list of folders in the path
- folders = [f for f in os.listdir(
- path) if os.path.isdir(os.path.join(path, f))]
-
- # Limit the number of runs if run_subset is True
- if run_subset:
- folders = folders[:n_runs]
- else:
- n_runs = len(folders)
-
- # Initialize the dictionary to store the data for all regions
- all_regions_data = {}
-
- # Loop through the folders
- for folder in tqdm(folders, desc=f"Processing {'Conflict' if c else 'No Conflict'} Runs"):
- # Get the list of files in the folder
- folder_path = os.path.join(path, folder)
-
- # Limit the files to the regions of interest if include_regions_of_interest is True
- if include_regions_of_interest:
- files = [f for f in os.listdir(folder_path) if f.split('.')[
- 0] in regions_of_interest]
- else:
- files = os.listdir(folder_path)
-
- # Check if region should be included based on the include_conflict_regions_only flag and conflict_regions list
- for file in files:
- # Get the region name from the file name
- region = file.split('.')[0]
-
- # Load the data from the file
- file_path = os.path.join(folder_path, file)
- data = pd.read_pickle(file_path)
-
- # t is the time index
- t = list(data.keys())
-
- # Get the consumption recovery data for each region
- all_region_hh = [data[i]['c_t'].rename(
- i) for i in t if not data[i].empty]
-
- # Concatenate the data for all households in the region
- all_regions_data[region] = pd.concat(all_region_hh, axis=1)
-
- # Store the results in the dictionary
- results['Conflict' if c else 'No Conflict'] = all_regions_data
-
- # Save the results to a CSV file
- if save_results:
- results_path = os.path.abspath(
- f'../../experiments/{country}/consumption_recovery/')
- if not os.path.exists(results_path):
- os.makedirs(results_path)
- for run_type, regions_data in results.items():
- for region, data in regions_data.items():
- data.to_csv(f'{results_path}/{run_type}_{region}_{n_runs}.csv')
-
- return results
-
-
-def load_consumption_data(country: str = 'Nigeria') -> list:
- '''Load the prepared consumption recovery data.'''
- # List the files in the folder
- folder = f'../../experiments/{country}/consumption_recovery/'
- files = os.listdir(folder)
-
- # Get the regional and mean files
- regional_files = [f for f in files if 'mean' not in f]
-
- # Ignore files if these are folders
- regional_files = [f for f in regional_files if '.' in f]
-
- # Load the data from the regional files
- # Differentiate between conflict and no conflict
- conflict_regional_data = {}
- no_conflict_regional_data = {}
-
- for file in regional_files:
- # Get the region name from the file name
- region = file.split('_')[1]
- # Get the conflict status from the file name
- conflict_status = 'No Conflict' if 'No Conflict' in file else 'Conflict'
- # Load the data from the file
- data = pd.read_csv(folder + file, index_col=0)
- # Store the data in the appropriate dictionary
- if conflict_status == 'Conflict':
- conflict_regional_data[region] = data
- else:
- no_conflict_regional_data[region] = data
-
- return conflict_regional_data, no_conflict_regional_data
-
-
-filter_and_save_consumption_data(save_results=True)
diff --git a/unbreakable/analysis/visualizer.py b/unbreakable/analysis/visualizer.py
deleted file mode 100644
index 548d4cf..0000000
--- a/unbreakable/analysis/visualizer.py
+++ /dev/null
@@ -1,543 +0,0 @@
-import geopandas as gpd
-import matplotlib
-import matplotlib.pyplot as plt
-import pandas as pd
-import numpy as np
-from sklearn.preprocessing import MinMaxScaler
-import ptitprince as pt
-import seaborn as sns
-from scipy.stats import spearmanr
-from matplotlib.ticker import MaxNLocator
-import mapclassify as mc
-from mycolorpy import colorlist as mcp
-# import contextily as ctx
-
-
-def raincloud_plot(outcomes: pd.DataFrame, savefig: bool, color_palette: str = 'Set2', sharex: bool = True):
- '''Visualize the outcomes using a raincloud plot.
-
- Args:
- outcomes (pd.DataFrame): The outcomes dataframe.
- savefig (bool): Whether to save the figure or not.
- color_palette (str, optional): The color palette to use. Defaults to 'Set2'.
- sharex (bool, optional): Whether to share the x-axis or not. Defaults to True.
-
- Returns:
- None
- '''
-
- regions = outcomes['region'].unique().tolist()
- n_regions = len(regions)
- colors = sns.color_palette(color_palette, n_colors=len(regions))
-
- x_columns = [
- 'n_aff_people',
- 'n_new_poor_increase_pp',
- 'n_new_poor',
- 'annual_avg_consum_loss_pct',
- 'r',
- 'new_poverty_gap_initial',
- 'new_poverty_gap_all',
- ]
-
- x_titles = [
- 'Affected People',
- 'New Poor Increase (p.p.)',
- 'New Poor',
- f'Wt. Ann. Avg. Consump. Loss p.c. (%)',
- 'Socio-Economic Resilience',
- 'New Poverty Gap Initial Poor',
- 'New Poverty Gap All Poor']
-
- for x_column, x_title in zip(x_columns, x_titles):
- fig, ax = plt.subplots(ncols=3, nrows=4, figsize=(
- 4 * n_regions / 3, 3 * n_regions / 3), sharex=sharex)
-
- for region in regions:
- # Select the region
- df = outcomes[outcomes['region'] == region].copy()
-
- # Convert to float
- df[x_column] = df[x_column].astype(float)
-
- # Make a half violin plot
- pt.half_violinplot(x=x_column,
- y='policy',
- data=df,
- color=colors[regions.index(region)],
- bw=.2,
- cut=0.,
- scale="area",
- width=.6,
- inner=None,
- ax=ax[regions.index(region) // 3, regions.index(region) % 3])
-
- # Add stripplot
- sns.stripplot(x=x_column,
- y='policy',
- data=df,
- color=colors[regions.index(region)],
- edgecolor='white',
- size=3,
- jitter=1,
- zorder=0,
- orient='h',
- ax=ax[regions.index(region) // 3, regions.index(region) % 3])
-
- # Add boxplot
- sns.boxplot(x=x_column,
- y='policy',
- data=df,
- color="black",
- width=.15,
- zorder=10,
- showcaps=True,
- boxprops={'facecolor': 'none', "zorder": 10},
- showfliers=True,
- whiskerprops={'linewidth': 2, "zorder": 10},
- saturation=1,
- orient='h',
- ax=ax[regions.index(region) // 3, regions.index(region) % 3])
-
- # Set title
- title = region
- ax[regions.index(region) // 3,
- regions.index(region) % 3].set_title(title)
- ax[regions.index(region) // 3,
- regions.index(region) % 3].set_ylabel('')
- ax[regions.index(region) // 3,
- regions.index(region) % 3].set_xlabel(x_title)
-
- # Remove y ticks and labels
- ax[regions.index(region) // 3,
- regions.index(region) % 3].set_yticklabels([])
- ax[regions.index(region) // 3,
- regions.index(region) % 3].set_yticks([])
-
- # Do not display floats in the x-axis
- ax[regions.index(region) // 3, regions.index(region) %
- 3].xaxis.set_major_locator(MaxNLocator(integer=True))
-
- # Add text close to the boxplot's median
- ax[regions.index(region) // 3, regions.index(region) % 3].text(df[x_column].median(), 0.2,
- f'M={df[x_column].median():.2f}',
- horizontalalignment='left', size='small', color='black')
- # Remove 2 last subplots
- ax[3, 1].set_visible(False)
- ax[3, 2].set_visible(False)
- fig.tight_layout()
- if savefig:
- plt.savefig(
- f'../reports/figures/analysis/{x_column}.png', dpi=500, bbox_inches='tight')
- plt.savefig(
- f'../reports/figures/analysis/{x_column}.pgf', bbox_inches='tight')
-
-
-def bivariate_choropleth(data: gpd.GeoDataFrame, x_name: str, y_name: str, x_label: str, y_label: str, scheme: str, figsize: tuple, return_table: bool) -> None:
- '''Create a bivariate choropleth map.
-
- Args:
- data (gpd.GeoDataFrame): Outcomes data frame.
- x_name (str): The name of the first variable.
- y_name (str): The name of the second variable.
- x_label (str): The label of the first variable.
- y_label (str): The label of the second variable.
- scheme (str): The scheme to use for binning the data.
- figsize (tuple): The size of the figure.
- return_table (bool): Whether to return the data frame or not.
-
- Returns:
- None
- '''
-
- fig, ax = plt.subplots(figsize=figsize)
-
- # TODO: Allow for 5 classes
- # Bin the data
- data = bin_data(data, x_name, y_name, scheme, print_statistics=False)
-
- # Get colors
- all_colors, available_colors = get_colors(data)
- cmap = matplotlib.colors.ListedColormap(available_colors)
-
- # Step 1: Draw the map
- # border = gpd.read_file(f'../data/processed/boundaries/{city}/city.json')
- border = gpd.read_file(
- '../data/raw/shapefiles/Saint Lucia/gadm36_LCA_shp/gadm36_LCA_0.shp')
- data.plot(ax=ax,
- edgecolor='black',
- linewidth=.1,
- column='Bi_Class', # variable that is going to be used to color the map
- cmap=cmap, # newly defined bivariate cmap
- categorical=True, # bivariate choropleth has to be colored as categorical map
- legend=False) # we're going to draw the legend ourselves
- # add the basemap
- # ctx.add_basemap(ax=ax, source=ctx.providers.CartoDB.Positron)
- border.plot(ax=ax, facecolor='none',
- edgecolor='black', alpha=.5) # city border
- for idx, row in data.iterrows():
- ax.annotate(text=row['NAME_1'], xy=row['geometry'].centroid.coords[0],
- ha='center', fontsize=8, color='white')
-
- plt.tight_layout() # "tighten" two figures map and basemap
- plt.axis('off') # we don't need axis with coordinates
- # ax.set_title('Bivariate Choropleth Amsterdam')
-
- # Step 2: draw the legend
-
- # We're drawing a 3x3 "box" as 3 columns
- # The xmin and xmax arguments axvspan are defined to create equally sized small boxes
-
- img2 = fig # refer to the main figure
- # add new axes to place the legend there
- ax2 = fig.add_axes([0.15, 0.25, 0.1, 0.1])
- # and specify its location
- alpha = 1 # alpha argument to make it more/less transparent
-
- # Column 1
- # All colors to create a complete legend
- # all_colors = ['#e8e8e8', '#b0d5df', '#64acbe', '#e4acac', '#ad9ea5', '#627f8c', '#c85a5a', '#985356', '#574249']
-
- ax2.axvspan(xmin=0, xmax=0.33, ymin=0, ymax=0.33,
- alpha=alpha, color=all_colors[0])
- ax2.axvspan(xmin=0, xmax=0.33, ymin=0.33, ymax=0.66,
- alpha=alpha, color=all_colors[1])
- ax2.axvspan(xmin=0, xmax=0.33, ymin=0.66, ymax=1,
- alpha=alpha, color=all_colors[2])
-
- # Column 2
- ax2.axvspan(xmin=0.33, xmax=0.66, ymin=0, ymax=0.33,
- alpha=alpha, color=all_colors[3])
- ax2.axvspan(xmin=0.33, xmax=0.66, ymin=0.33, ymax=0.66,
- alpha=alpha, color=all_colors[4])
- ax2.axvspan(xmin=0.33, xmax=0.66, ymin=0.66, ymax=1,
- alpha=alpha, color=all_colors[5])
-
- # Column 3
- ax2.axvspan(xmin=0.66, xmax=1, ymin=0, ymax=0.33,
- alpha=alpha, color=all_colors[6])
- ax2.axvspan(xmin=0.66, xmax=1, ymin=0.33, ymax=0.66,
- alpha=alpha, color=all_colors[7])
- ax2.axvspan(xmin=0.66, xmax=1, ymin=0.66, ymax=1,
- alpha=alpha, color=all_colors[8])
-
- # Step 3: annoate the legend
- # remove ticks from the big box
- ax2.tick_params(axis='both', which='both', length=0)
- ax2.axis('off') # turn off its axis
- ax2.annotate("", xy=(0, 1), xytext=(0, 0), arrowprops=dict(
- arrowstyle="->", lw=1, color='black')) # draw arrow for x
- ax2.annotate("", xy=(1, 0), xytext=(0, 0), arrowprops=dict(
- arrowstyle="->", lw=1, color='black')) # draw arrow for y
- ax2.text(s=x_label, x=0.1, y=-0.25, fontsize=8) # annotate x axis
- ax2.text(s=y_label, x=-0.25, y=0.1, rotation=90,
- fontsize=8) # annotate y axis
- # plt.savefig('bivariate_choropleth.png', dpi=300)
-
- if return_table:
- return data
-
-
-def nine_quadrants_plot(data: pd.DataFrame, x_name: str, y_name: str, scale: bool = True) -> None:
- '''Create a nine quadrants plot.
-
- Args:
- data (pd.DataFrame): Outcomes data frame.
- x_name (str): The name of the first variable.
- y_name (str): The name of the second variable.
- scale (bool, optional): Whether to scale the data or not. Defaults to True.
-
- Returns:
- None
- '''
- _, ax = plt.subplots(figsize=(6, 5))
-
- if scale:
- scaler = MinMaxScaler()
- data[x_name] = scaler.fit_transform(data[x_name].values.reshape(-1, 1))
- data[y_name] = scaler.fit_transform(data[y_name].values.reshape(-1, 1))
-
- data.plot.scatter(x_name, y_name, s=20, ax=ax, c='black', zorder=2)
-
- # Iterate over each row and annotate the points
- for idx, row in data.iterrows():
- ax.annotate(text=row['NAME_1'], xy=(row[x_name], row[y_name]),
- ha='center', fontsize=10, color='black')
-
- # Annotate with Spearman's rho
- # rho, p = spearmanr(data[x_name], data[y_name])
- # ax.text(0.05, 0.95, f'$\\rho$ = {round(rho, 2)}', transform=ax.transAxes,
- # verticalalignment='top', fontsize=12, bbox=dict(facecolor='white', edgecolor='black', alpha=1))
-
- ax.axvline(0.33, color='black', alpha=.33, lw=1)
- ax.axvline(0.66, color='black', alpha=.33, lw=1)
- ax.axhline(0.33, color='black', alpha=.33, lw=1)
- ax.axhline(0.66, color='black', alpha=.33, lw=1)
-
- alpha = 1
-
- all_colors = {'1A': '#dddddd',
- '1B': '#dd7c8a',
- '1C': '#cc0024',
- '2A': '#7bb3d1',
- '2B': '#8d6c8f',
- '2C': '#8a274a',
- '3A': '#016eae',
- '3B': '#4a4779',
- '3C': '#4b264d'}
-
- # Column 1
- c = all_colors['1A']
- ax.axvspan(xmin=0, xmax=0.33, ymin=0 + 0.025,
- ymax=0.345, alpha=alpha, color=c)
-
- c = all_colors['1B']
- ax.axvspan(xmin=0, xmax=0.33, ymin=0.33 + 0.015,
- ymax=0.66 - 0.015, alpha=alpha, color=c)
-
- c = all_colors['1C']
- ax.axvspan(xmin=0, xmax=0.33, ymin=0.66 - 0.015,
- ymax=1 - 0.05, alpha=alpha, color=c)
-
- # Column 2
- c = all_colors['2A']
- ax.axvspan(xmin=0.33, xmax=0.66, ymin=0 + 0.025,
- ymax=0.345, alpha=alpha, color=c)
-
- c = all_colors['2B']
- ax.axvspan(xmin=0.33, xmax=0.66, ymin=0.345,
- ymax=0.645, alpha=alpha, color=c)
-
- c = all_colors['2C']
- ax.axvspan(xmin=0.33, xmax=0.66, ymin=0.649,
- ymax=1 - 0.05, alpha=alpha, color=c)
-
- # Column 3
- c = all_colors['3A']
- ax.axvspan(xmin=0.66, xmax=1, ymin=0.025, ymax=0.345, alpha=alpha, color=c)
-
- c = all_colors['3B']
- ax.axvspan(xmin=0.66, xmax=1, ymin=0.345,
- ymax=0.645, alpha=alpha, color=c)
-
- c = all_colors['3C']
- ax.axvspan(xmin=0.66, xmax=1, ymin=0.649,
- ymax=1 - 0.05, alpha=alpha, color=c)
-
- ax.set_xlim(-.05, 1.05)
- ax.set_ylim(-0.05, 1.05)
-
- # Add regression line
- # x = data[x_name]
- # y = data[y_name]
- # m, b = np.polyfit(x, y, 1)
- # ax.plot(x, m * x + b, color='black', alpha=0.5, zorder=1)
-
-
-def get_colors(data: pd.DataFrame) -> list:
- '''Get colors for the bivariate choropleth map.'''
-
- # colors = ['#e8e8e8', # 1A
- # '#b0d5df', # 1B
- # # '#64acbe', # 1C
- # '#e4acac', # 2A
- # '#ad9ea5', # 2B
- # '#627f8c', # 2C
- # '#c85a5a', # 3A
- # '#985356'] # , # 3B
- # # '#574249'] # 3C
-
- all_colors = {'1A': '#e8e8e8',
- '1B': '#b0d5df',
- '1C': '#64acbe',
- '2A': '#e4acac',
- '2B': '#ad9ea5',
- '2C': '#627f8c',
- '3A': '#c85a5a',
- '3B': '#985356',
- '3C': '#574249'}
-
- all_colors = {'1A': '#dddddd',
- '1B': '#dd7c8a',
- '1C': '#cc0024',
- '2A': '#7bb3d1',
- '2B': '#8d6c8f',
- '2C': '#8a274a',
- '3A': '#016eae',
- '3B': '#4a4779',
- '3C': '#4b264d'}
-
- # Set of colors matching the elements of Bi_Class
- # We have to exclude those that did not come up in the data
- available_classes = data['Bi_Class'].value_counts().sort_index().index
- available_colors = [all_colors[i] for i in available_classes]
- return list(all_colors.values()), available_colors
-
-
-def bin_data(data: gpd.GeoDataFrame, x_name: str, y_name: str, scheme: str = 'fisher_jenks', print_statistics: bool = True) -> gpd.GeoDataFrame:
- '''Bin the data for the bivariate choropleth map.
-
- Args:
- data (gpd.GeoDataFrame): Outcomes data frame.
- x_name (str): The name of the first variable.
- y_name (str): The name of the second variable.
- scheme (str): The scheme to use for binning the data.
- print_statistics (bool, optional): Whether to print statistics or not. Defaults to True.
-
- Returns:
- data (gpd.GeoDataFrame): The outcomes data frame with the binned data.
- '''
- if scheme == 'fisher_jenks':
- x_classifier = mc.FisherJenks(data[x_name], k=3)
- # x_bin_edges = x_classifier.bins
- x_bin_labels = x_classifier.yb
-
- y_classifier = mc.FisherJenks(data[y_name], k=3)
- # y_bin_edges = y_classifier.bins
- y_bin_labels = y_classifier.yb
-
- # Bin the first variable - x
- data['Var1_Class'] = x_bin_labels
- data['Var1_Class'] = data['Var1_Class'].astype('str')
-
- # Bin the second variable - y
- data['Var2_Class'] = y_bin_labels
- data['Var2_Class'] = data['Var2_Class'].astype('str')
-
- # Code created x bins to 1, 2, 3
- d = {'0': '1', '1': '2', '2': '3'}
- data['Var1_Class'] = data['Var1_Class'].replace(d)
-
- # Code created y bins to A, B, C
- d = {'0': 'A', '1': 'B', '2': 'C'}
- data['Var2_Class'] = data['Var2_Class'].replace(d)
-
- # Combine x and y codes to create Bi_Class
- data['Bi_Class'] = data['Var1_Class'].astype('str') + data['Var2_Class']
-
- if print_statistics:
- print('Number of unique elements in Var1_Class =',
- len(data['Var1_Class'].unique()))
- print('Number of unique elements in Var2_Class =',
- len(data['Var2_Class'].unique()))
- print('Number of unique elements in Bi_Class =',
- len(data['Bi_Class'].unique()))
- return data
-
-
-def annotated_hist(outcomes: pd.DataFrame, annotate: bool) -> None:
- '''Create an annotated histogram of the annual average consumption loss.
-
- Args:
- outcomes (pd.DataFrame): Outcomes data frame.
- annotate (bool): Whether to annotate the plot or not.
-
- Returns:
- None
- '''
- sns.histplot(outcomes['annual_avg_consum_loss_pct'],)
- plt.xlabel('Annual Average Consumption Loss PC (%)')
- plt.ylabel('Run count')
-
- plt.axvline(outcomes['annual_avg_consum_loss_pct'].min(
- ), color='red', linestyle='dashed', linewidth=1)
- plt.axvline(outcomes['annual_avg_consum_loss_pct'].max(
- ), color='red', linestyle='dashed', linewidth=1)
- plt.axvline(outcomes['annual_avg_consum_loss_pct'].median(
- ), color='black', linestyle='dashed', linewidth=1)
-
- if annotate:
- plt.annotate(f"{outcomes['annual_avg_consum_loss_pct'].min():.2f}%",
- xy=(outcomes['annual_avg_consum_loss_pct'].min(), 0),
- xytext=(
- outcomes['annual_avg_consum_loss_pct'].min() - 5, 100),
- arrowprops=dict(facecolor='black', shrink=0.05),
- horizontalalignment='right', verticalalignment='top')
- plt.annotate(f"{outcomes['annual_avg_consum_loss_pct'].max():.2f}%",
- xy=(outcomes['annual_avg_consum_loss_pct'].max(), 0),
- xytext=(
- outcomes['annual_avg_consum_loss_pct'].max() + 5, 100),
- arrowprops=dict(facecolor='black', shrink=0.05),
- horizontalalignment='left', verticalalignment='top')
- plt.annotate(f"{outcomes['annual_avg_consum_loss_pct'].median():.2f}%",
- xy=(outcomes['annual_avg_consum_loss_pct'].median(), 0),
- xytext=(
- outcomes['annual_avg_consum_loss_pct'].median() + 5, 100),
- arrowprops=dict(facecolor='black', shrink=0.05),
- horizontalalignment='left', verticalalignment='top')
- sns.despine()
- plt.tight_layout()
-
-
-def coloured_density_plots(outcomes: pd.DataFrame, scheme: str, k: int, cmap: str = "OrRd", legend: bool = True) -> None:
- '''Make colored density plots for each region. Color here matches the color of the choropleth map.
-
- Args:
- outcomes (pd.DataFrame): Outcomes data frame.
- scheme (str, optional): The scheme to use for binning the data.
- k (int, optional): The number of bins.
- cmap (str, optional): The name of the colormap to use. Defaults to "OrRd".
-
- Returns:
- None
- '''
- # Choropleth map uses median values to classify the regions, we're going to do the same
- median_outcomes = outcomes.groupby('region').median(numeric_only=True)[
- ['annual_avg_consum_loss_pct']]
-
- # The map used equalinterval scheme, but it would be beneficial to allow for other schemes
- if scheme == 'equal_intervals':
- classifier = mc.EqualInterval(median_outcomes.values, k=k)
- elif scheme == 'fisher_jenks':
- classifier = mc.FisherJenks(median_outcomes.values, k=k)
- else:
- raise ValueError(
- 'Invalid scheme. Please use `equal_intervals` or `fisher_jenks`')
-
- # Get the bin edges and labels
- bin_edges = classifier.bins
- bin_labels = classifier.yb
-
- # Map the region to the bin label
- region_to_label_mapper = dict(zip(median_outcomes.index, bin_labels))
-
- # Map the bin label to a color
- colors = mcp.gen_color(cmap=cmap, n=k)
- label_color_mapper = dict(zip(np.arange(0, k), colors))
-
- regions = outcomes['region'].unique().tolist()
- fig, ax = plt.subplots()
-
- # Get regions with min and max values
- descr = outcomes.iloc[:, 2:-1].groupby('region').describe()[
- ['annual_avg_consum_loss_pct']]
- min_distr = descr['annual_avg_consum_loss_pct']['50%'].idxmin()
- max_distr = descr['annual_avg_consum_loss_pct']['50%'].idxmax()
-
- # Make the density plots
- for region in regions:
- df = outcomes[outcomes['region'] == region]
- region_label = region_to_label_mapper[region]
- label_color = label_color_mapper[region_label]
- color = label_color
-
- # Make the line thicker for regions with min and max values
- if region in [min_distr, max_distr]:
- linewidth = 5
- else:
- linewidth = 1
- sns.kdeplot(data=df, x='annual_avg_consum_loss_pct',
- ax=ax, color=color, linewidth=linewidth, alpha=1)
-
- ax.set_xlabel('Annual Average Consumption Loss PC (%)')
- ax.set_ylabel('Run density')
- ax.spines['right'].set_visible(False)
- ax.spines['top'].set_visible(False)
- ax.spines['left'].set_visible(False)
- ax.spines['bottom'].set_visible(False)
- ax.set_facecolor('lightgray')
-
- if legend:
- # Move legend outside the plot
- ax.legend(regions, title='Region', frameon=False)
- ax.get_legend().set_bbox_to_anchor((1, 1))
diff --git a/unbreakable/data/generator.py b/unbreakable/data/generator.py
deleted file mode 100644
index ca2206c..0000000
--- a/unbreakable/data/generator.py
+++ /dev/null
@@ -1,82 +0,0 @@
-import numpy as np
-import pandas as pd
-import numpy as np
-import seaborn as sns
-import scipy.stats as stats
-
-
-def generate_households(num_households=1, conflict_intensity: str = 'None', fix_seed=True):
- '''Generate dummy households.'''
- if fix_seed:
- np.random.seed(0) # Ensure reproducibility
-
- data = {'exp_house': 0,
- 'consumption_loss': 0,
- 'consumption_loss_npv': 0,
- 'net_consumption_loss': 0,
- 'net_consumption_loss_npv': 0,
- 'c_t': 0,
- 'c_t_unaffected': 0,
- 'wellbeing': 0}
-
- if conflict_intensity != 'None':
- d = {'Very low': {'mean': 1522.72, 'std': 980.51, 'min': 154.25, 'max': 5473.81},
- 'Low': {'mean': 1333.83, 'std': 799.99, 'min': 226.35, 'max': 5439.8},
- 'Medium': {'mean': 982.08, 'std': 666.34, 'min': 175.05, 'max': 5317.89},
- 'High': {'mean': 1064.61, 'std': 809.55, 'min': 156.39, 'max': 5439.94},
- 'Very high': {'mean': 637.02, 'std': 474.87, 'min': 152.8, 'max': 5172.65}}
-
- lower, upper = d[conflict_intensity]['min'], d[conflict_intensity]['max']
- mu, sigma = d[conflict_intensity]['mean'], d[conflict_intensity]['std']
- X = stats.truncnorm((lower - mu) / sigma,
- (upper - mu) / sigma, loc=mu, scale=sigma)
- exp = X.rvs(num_households)
- else:
- # Let's take q=0.25 and q=0.75 as the lower and upper bounds
- lower, upper = 153, 5474
- mu, sigma = 1099, 1099
- X = stats.truncnorm((lower - mu) / sigma,
- (upper - mu) / sigma, loc=mu, scale=sigma)
- exp = X.rvs(num_households)
-
- data['exp'] = exp
- # Income is a product of expenditure and a random coefficient
- inc_multiplier = 1.48 # for Nigeria
- inc_delta = 0.1
- low = inc_multiplier - inc_delta
- high = inc_multiplier + inc_delta
- data['inc'] = data['exp'] * np.random.uniform(low, high)
-
- sav_multiplier = 0.0204 # for Nigeria
- sav_delta = 0.02
- low = sav_multiplier - sav_delta
- high = sav_multiplier + sav_delta
- data['sav'] = data['inc'] * np.random.uniform(low, high)
-
- # divide by average productivity, 0.35 for Nigeria
- data['keff'] = data['inc'] / 0.35
-
- mean_vulnerability = {'Very low': 0.43,
- 'Low': 0.46,
- 'Medium': 0.66,
- 'High': 0.63,
- 'Very high': 0.65}
-
- if conflict_intensity != 'None':
- data['v'] = mean_vulnerability[conflict_intensity]
- else:
- data['v'] = np.random.uniform(0.2, 0.8, num_households)
-
- # Sort columns
- sorted_columns = ['exp', 'inc', 'sav', 'keff', 'exp_house', 'v', 'consumption_loss', 'consumption_loss_npv',
- 'net_consumption_loss', 'net_consumption_loss_npv', 'c_t', 'c_t_unaffected', 'wellbeing']
-
- return pd.DataFrame(data)[sorted_columns]
-
-
-def generate_risk_and_damage():
- pass
-
-
-def generate_conflict():
- pass
diff --git a/unbreakable/data/randomizer.py b/unbreakable/data/randomizer.py
deleted file mode 100644
index 17c0bc7..0000000
--- a/unbreakable/data/randomizer.py
+++ /dev/null
@@ -1,522 +0,0 @@
-import numpy as np
-import pandas as pd
-
-
-def randomize(households: pd.DataFrame, risk_and_damage: pd.DataFrame,
- params: dict, random_seed: int, print_statistics: bool = False) -> pd.DataFrame:
- '''
- Randomize household data, resample it and match it with risk data.
-
- Args:
- households: Households.
- params: Dictionary with parameters for randomization.
- random_seed: Random seed.
- print_statistics: Whether to print statistics.
-
- Returns:
- households: Randomized and resampled households.
- '''
- # Ensure reproducibility
- if random_seed is not None:
- np.random.seed(random_seed)
- households['random_seed'] = random_seed
-
- # Save country and return period
- households['country'] = params['country']
- households['return_period'] = params['return_period']
-
- # Extra necessary parameters
- rnd_inc_params = params['rnd_inc_params']
- rnd_sav_params = params['rnd_sav_params']
- rnd_rent_params = params['rnd_rent_params']
- avg_prod = params['avg_prod']
- rnd_house_vuln_params = params['rnd_house_vuln_params']
- min_households = params['min_households']
- atol = params['atol']
-
- # Randomize household data
- households = rnd_income(households, rnd_inc_params)
- households = rnd_savings(households, rnd_sav_params)
- households = rnd_rent(households, rnd_rent_params)
- households = calc_dwelling_value(households, avg_prod)
- households = rnd_house_vuln(households, rnd_house_vuln_params)
-
- # Resample households to be more representative
- households = resample_households(households, min_households, random_seed)
-
- # Match household survey assets with risk and asset damage data
- households = match_survey_with_risk_data(
- households, risk_and_damage, atol, print_statistics)
-
- return households
-
-
-# ---------------------------------------------------------------------------- #
-# Randomize household survey data #
-# ---------------------------------------------------------------------------- #
-
-
-def rnd_inc_mult(size: int, **params) -> np.ndarray:
- # NOTE: `normal` is to showcase the flexibility of the function,
- # we cannot use it for income generation as it can produce negative values
- '''Randomize income multiplier based on the specified parameters.'''
- distr = params.get('distr')
- if distr == 'uniform':
- low = params.get('inc_mult') - params.get('delta')
- high = params.get('inc_mult') + params.get('delta')
- if low < 0:
- raise ValueError("Low income cannot be negative.")
- return np.random.uniform(low, high, size)
- elif distr == 'normal':
- loc = params.get('loc')
- scale = params.get('scale')
- return np.random.normal(loc, scale, size)
- else:
- raise ValueError(
- f"Distribution '{distr}' is not supported yet.")
-
-
-def rnd_income(households: pd.DataFrame, rnd_income_params: dict) -> pd.DataFrame:
- '''Randomize household income.'''
- if rnd_income_params['randomize']:
- households = households.copy()
- size = households.shape[0]
-
- # Apply income generation for regions or country as applicable
- if households['rgn_inc_mult'].notna().any():
- for region in households['region'].unique():
- mask = households['region'] == region
- rnd_income_params['inc_mult'] = households.loc[mask,
- 'rgn_inc_mult'].iloc[0]
- size = mask.sum()
- inc_mult_rnd = rnd_inc_mult(size, **rnd_income_params)
-
- # Estimate income as a product of expenditure and income multiplier
- households.loc[mask, 'inc'] = households.loc[mask,
- 'exp'] * inc_mult_rnd
- elif households['ctry_inc_mult'].notna().any():
- rnd_income_params['inc_mult'] = households['ctry_inc_mult'].iloc[0]
- inc_mult_rnd = rnd_inc_mult(size, **rnd_income_params)
- # Estimate income as a product of expenditure and income multiplier
- households['inc'] = households['exp'] * inc_mult_rnd
- else:
- raise ValueError("No income multiplier found.")
-
- assert not households['inc'].isna().any(), "Income cannot be NaN"
- assert not (households['inc'] < 0).any(), "Income cannot be negative"
- assert not (households['inc'] == 0).any(), "Income cannot be 0"
- return households
-
- else:
- return households
-
-
-def rnd_sav_mult(size: int, **params):
- """Randomize savings multiplier based on the specified distribution."""
- # NOTE: `normal` is to showcase the flexibility of the function,
- # we cannot use it for income generation as it can produce negative values
- distr = params.get('distr')
- if distr == 'uniform':
- low = params.get('low')
- high = params.get('high')
- return np.random.uniform(low, high, size)
- elif distr == 'normal':
- loc = params.get('loc')
- scale = params.get('scale')
- return np.random.normal(loc, scale, size)
- else:
- raise ValueError(f"Distribution '{distr}' is not supported yet.")
-
-
-def rnd_savings(households: pd.DataFrame, rnd_savings_params: dict) -> pd.DataFrame:
- '''Randomize household savings.'''
- if rnd_savings_params['randomize']:
- # Get function parameters
- distr = rnd_savings_params['distr']
- size = households.shape[0]
-
- # Ensure that the distribution is supported
- if distr == 'uniform':
- low = rnd_savings_params.get(
- 'avg') - rnd_savings_params.get('delta')
- high = rnd_savings_params.get(
- 'avg') + rnd_savings_params.get('delta')
- if low < 0:
- raise ValueError("Low savings cannot be negative.")
- rnd_savings_params.update({'low': low, 'high': high})
-
- else:
- raise ValueError(f"Distribution '{distr}' is not supported yet.")
-
- # Randomize savings multiplier using the distribution-specific function
- sav_mult_rnd = rnd_sav_mult(size, **rnd_savings_params)
-
- # Estimate savings as a product of income and savings multiplier
- households['sav'] = households['inc'] * sav_mult_rnd
-
- assert not households['sav'].isna().any(), "Savings cannot be NaN"
- assert not (households['sav'] < 0).any(), "Savings cannot be negative"
- assert not (households['sav'] == 0).any(), "Savings cannot be 0"
-
- return households
- else:
- return households
-
-
-def rnd_rent_mult(size: int, **params):
- """Randomize rent multiplier based on the specified distribution."""
- # NOTE: `normal` is to showcase the flexibility of the function,
- # we cannot use it for income generation as it can produce negative values
- distr = params.get('distr')
- if distr == 'uniform':
- low = params.get('low')
- high = params.get('high')
- return np.random.uniform(low, high, size)
- elif distr == 'normal':
- loc = params.get('loc')
- scale = params.get('scale')
- return np.random.normal(loc, scale, size)
- else:
- raise ValueError(f"Distribution '{distr}' is not supported yet.")
-
-
-def rnd_rent(households: pd.DataFrame, rnd_rent_params: dict) -> pd.DataFrame:
- '''Randomize household rent.'''
- if rnd_rent_params['randomize']:
- # Get function parameters
- distr = rnd_rent_params['distr']
- size = households.shape[0]
-
- # Ensure that the distribution is supported
- if distr == 'uniform':
- low = rnd_rent_params.get('avg') - rnd_rent_params.get('delta')
- high = rnd_rent_params.get('avg') + rnd_rent_params.get('delta')
- if low < 0:
- raise ValueError("Low rent cannot be negative.")
- rnd_rent_params.update({'low': low, 'high': high})
-
- else:
- raise ValueError(f"Distribution '{distr}' is not supported yet.")
-
- # Generate savings using the distribution-specific function
- rent_mult_rnd = rnd_rent_mult(size, **rnd_rent_params)
-
- # Assign rent as a product of exp and rent multiplier to each of the rows
- households['exp_house'] = households['exp'].mul(rent_mult_rnd)
-
- assert not households['exp_house'].isna().any(), "Rent cannot be NaN"
- assert not (households['exp_house'] <
- 0).any(), "Rent cannot be negative"
- assert not (households['exp_house'] == 0).any(), "Rent cannot be 0"
-
- # Remove rent for the households that own
- households.loc[households['own_rent'] == 'own', 'exp_house'] = 0
-
- return households
- else:
- return households
-
-
-def calc_dwelling_value(households: pd.DataFrame, avg_prod: float) -> pd.DataFrame:
- '''Calculate dwelling value based on the average productivity.'''
- # Get the dwelling value for the households that own
- households.loc[households['own_rent'] == 'own',
- 'k_house'] = households['inc'] / avg_prod
-
- # Set the dwelling value to 0 for the households that rent
- households.loc[households['own_rent'] == 'rent',
- 'k_house'] = 0
-
- assert not households['k_house'].isna(
- ).any(), "Dwelling value cannot be NaN"
- assert not (households['k_house'] < 0).any(
- ), "Dwelling value cannot be negative"
-
- return households
-
-
-def rnd_house_vuln(households: pd.DataFrame, rnd_house_vuln_params: dict) -> pd.DataFrame:
- '''
- Randomize house vulnerability.
-
- Args:
- households: Households
- Required columns: 'v_init' (initial vulnerability)
- rnd_house_vuln_params: Dictionary with parameters for randomization.
-
- Returns:
- households: Households with randomized vulnerability.
-
- Raises:
- ValueError: If the distribution is not supported.
- '''
- if rnd_house_vuln_params['randomize']:
- distr = rnd_house_vuln_params['distr']
- if distr == 'uniform':
- # Unpack parameters
- low = rnd_house_vuln_params['low'] # default 0.8
- high = rnd_house_vuln_params['high'] # default 1.0
- max_thresh = rnd_house_vuln_params['max_thresh'] # default 0.9
- min_thresh = rnd_house_vuln_params['min_thresh'] # default 0.2
-
- # Multiply initial vulnerability by a random value
- households['v'] = households['v_init'] * \
- np.random.uniform(low, high, households.shape[0])
-
- # Limit vulnerability to a threshold, since under extreme values, recovery rate skyrockets
- households.loc[households['v'] > max_thresh, 'v'] = max_thresh
- households.loc[households['v'] < min_thresh, 'v'] = min_thresh
- else:
- raise ValueError("Only uniform distribution is supported yet.")
- return households
- else:
- return households
-
-# ---------------------------------------------------------------------------- #
-# Duplicate households-related #
-# ---------------------------------------------------------------------------- #
-
-
-def resample_households(households: pd.DataFrame, min_households: int, random_seed: int) -> pd.DataFrame:
- '''Resample country households to be more representative in `identify_affected` function.
-
- Args:
- households (pd.DataFrame): Households.
- min_households (int): Minimum number of households for the country sample to be representative.
- random_seed (int): Random seed for reproducibility.
-
- Returns:
- pd.DataFrame: Resampled households.f
- '''
- sample = pd.DataFrame()
- households['id_orig'] = households['id']
- for rgn in households['region'].unique():
- rgn_households = households[households['region'] == rgn]
- # TODO: Remove this condition when the data is fixed
- if rgn != 'Borno':
- rgn_households = resample_region(
- rgn_households, min_households, random_seed)
- sample = pd.concat(
- [sample, rgn_households])
- sample['id'] = range(1, len(sample) + 1)
- sample.reset_index(drop=True, inplace=True)
- return sample
-
-
-def resample_region(households: pd.DataFrame, min_households: int, random_seed: int) -> pd.DataFrame:
- '''Weighted resampling with adjustment for household representation within a given region.
-
- Args:
- households (pd.DataFrame): Households of a specific region.
- min_households (int): Minimum number of households for the region sample to be representative.
- random_seed (int): Random seed for reproducibility.
-
- Returns:
- pd.DataFrame: Resampled households of a specific region.
-
- Raises:
- ValueError: If the total weights after resampling is not equal to the initial total weights.
- '''
-
- if len(households) < min_households:
- # Save the initial total weights
- initial_total_weights = households['wgt'].sum()
-
- # Save the original household id
- households = households.assign(
- id_orig=households['id'])
-
- # Sample households with replacement
- delta = min_households - len(households)
-
- # To avoid sampling one household
- if delta == 1:
- delta = 2
-
- # ?: Check if fixing np random seed is affecting pandas random sampling
- if random_seed is not None:
- sample = households.sample(
- n=delta, replace=True, random_state=random_seed)
- else:
- sample = households.sample(
- n=delta, replace=True)
-
- # Keep how many duplicates by index
- duplicates = sample.index.value_counts()
-
- # Combine the original and the sampled households
- duplicated_households = pd.concat(
- [households, sample], axis=0, sort=False)
-
- # Iterate over the duplicated households and update the weights
- for household_id in duplicates.index:
- # Get original weight
- original_weight = households.loc[household_id, 'wgt']
-
- # Count how many rows are there (could be one as well)
- n_duplicates = duplicates[household_id]
-
- # Update the weight
- duplicated_households.loc[household_id,
- 'wgt'] = original_weight / (n_duplicates + 1)
-
- # Get the new weight
- weights_after_duplication = duplicated_households.loc[household_id, 'wgt'].sum(
- )
-
- # Check if it is close to the original weight
- if not np.isclose(weights_after_duplication, original_weight, atol=1e-6):
- raise ValueError(
- 'Total weights after duplication is not equal to the initial total weights')
-
- if not np.isclose(duplicated_households['wgt'].sum(), initial_total_weights, atol=1e-6):
- raise ValueError(
- 'Total weights after duplication is not equal to the initial total weights')
-
- return duplicated_households.reset_index(drop=True)
- else:
- return households
-
-# ---------------------------------------------------------------------------- #
-# Matching household survey assets with risk and asset damage data #
-# ---------------------------------------------------------------------------- #
-
-
-def match_survey_with_risk_data(households: pd.DataFrame, risk_and_damage: pd.DataFrame, atol: int, print_statistics: bool = False) -> pd.DataFrame:
- # Initialize list to store matched households
- matched = []
-
- # Iterate over unique regions
- for region in households['region'].unique():
- # Filter households by region
- region_households = households[households['region'] == region].copy()
-
- # Compute survey assets
- region_households['survey_assets'] = region_households[[
- 'k_house', 'wgt']].prod(axis=1)
- survey_assets = region_households['survey_assets'].sum()
-
- # Get total exposed asset from disaster risk assessment for the given region
- disaster_assessment = risk_and_damage[risk_and_damage['region']
- == region].iloc[0]
- exposed_assets = disaster_assessment['total_exposed_stock']
-
- # Optionally print statistics
- if print_statistics:
- print_statistics_for_region(
- region, survey_assets, exposed_assets, region_households)
-
- # Match households with disaster risk assessment data
- df = match_assets(
- region_households, exposed_assets, atol=atol)
-
- # Recalculate survey assets
- df['survey_assets'] = df[['k_house', 'wgt']].prod(axis=1)
-
- # Assert that the assets match after matching
- assert round(exposed_assets) == round(
- df['survey_assets'].sum()), "Mismatch in assets after matching"
-
- matched.append(df)
-
- # Concatenate matched households and return
- return pd.concat(matched)
-
-
-def print_statistics_for_region(region: str, survey_assets: float, exposed_assets: float, households: pd.DataFrame):
- print('Region:', region)
- print('Household survey assets:', '{:,}'.format(round(survey_assets)))
- print('Disaster risk assessment assets:',
- '{:,}'.format(round(exposed_assets)))
- comparison_ratio = survey_assets / \
- exposed_assets if survey_assets > exposed_assets else exposed_assets / survey_assets
- print('Comparison:', '{:.2f} times'.format(comparison_ratio), 'bigger')
- print('Median expenditure:', '{:,}'.format(households['exp'].median()))
- print('Poverty line:', '{:,}'.format(households['povline'].values[0]))
- print('----------------------------------------\n')
-
-
-def check_asset_match(households: pd.DataFrame, tot_exposed_asset: float, atol: float) -> bool:
- '''Check if the total asset in the survey matches the total exposed asset.
-
- Args:
- households (pd.DataFrame): Households data.
- tot_exposed_asset (float): Total exposed asset stock from the damage data.
- atol (float): Absolute tolerance for the comparison.
-
- Returns:
- bool: True if the assets match within the specified tolerance, False otherwise.
- '''
- tot_asset_surv = households[['k_house', 'wgt']].prod(axis=1).sum()
- return np.isclose(tot_exposed_asset, tot_asset_surv, atol=atol)
-
-
-def adjust_assets(households: pd.DataFrame, tot_exposed_asset: float) -> pd.DataFrame:
- '''Adjusts the assets of the households to match the total exposed asset.
-
- Args:
- households (pd.DataFrame): Households data.
- tot_exposed_asset (float): Total exposed asset to match.
-
- Returns:
- pd.DataFrame: Adjusted households data.
- '''
- tot_asset_surv = households[['k_house', 'wgt']].prod(axis=1).sum()
- scaling_factor = tot_exposed_asset / tot_asset_surv
- households['tot_asset_surv'] = tot_asset_surv
- households['k_house'] *= scaling_factor
-
- return households
-
-
-def adjust_expenditure(households: pd.DataFrame, scaling_factor: float) -> pd.DataFrame:
- '''Adjusts the expenditure of the households based on the scaling factor.
-
- Args:
- households (pd.DataFrame): Households data.
- scaling_factor (float): Scaling factor for adjustment.
-
- Returns:
- pd.DataFrame: Households data with adjusted expenditure.
- '''
- households['exp'] *= scaling_factor
- households['exp_house'] *= scaling_factor
-
- return households
-
-
-def adjust_poverty_line(households: pd.DataFrame, scaling_factor: float) -> pd.DataFrame:
- '''Adjusts the poverty line of the households based on the scaling factor.
-
- Args:
- households (pd.DataFrame): Households data.
- scaling_factor (float): Scaling factor for adjustment.
-
- Returns:
- pd.DataFrame: Households data with adjusted poverty line.
- '''
- poverty_line = households['poverty_line'].iloc[0]
- households['poverty_line_adjusted'] = poverty_line * scaling_factor
-
- return households
-
-
-def match_assets(households: pd.DataFrame, tot_exposed_asset: float, atol: float) -> pd.DataFrame:
- '''Matches and possibly adjusts assets, poverty line and expenditure of households to the asset damage data.
-
- Args:
- households (pd.DataFrame): Households data.
- tot_exposed_asset (float): Total exposed asset from the damage data.
- atol (float): Absolute tolerance for the comparison.
-
- Returns:
- pd.DataFrame: Households with potentially adjusted assets, expenditure, and poverty line.
- '''
- if not check_asset_match(households, tot_exposed_asset, atol):
- tot_asset_surv = households[['k_house', 'wgt']].prod(axis=1).sum()
- scaling_factor = tot_exposed_asset / tot_asset_surv
- households = adjust_assets(households, tot_exposed_asset)
- households = adjust_expenditure(households, scaling_factor)
- households = adjust_poverty_line(households, scaling_factor)
-
- return households
diff --git a/unbreakable/data/reader.py b/unbreakable/data/reader.py
deleted file mode 100644
index e3e8741..0000000
--- a/unbreakable/data/reader.py
+++ /dev/null
@@ -1,58 +0,0 @@
-import pandas as pd
-import logging
-from pathlib import Path
-
-# Configure logging
-logging.basicConfig(level=logging.ERROR,
- format='%(asctime)s - %(levelname)s - %(message)s')
-
-
-def read_data_file(file_path: Path, file_type: str = 'csv', **kwargs) -> pd.DataFrame:
- '''
- Generic function to read a data file.
-
- Args:
- file_path (Path): Path object to the file.
- file_type (str): Type of the file ('xlsx' or 'csv').
- **kwargs: Additional keyword arguments for pandas read functions.
-
- Returns:
- pd.DataFrame: Data from the file.
-
- Raises:
- FileNotFoundError: If the file does not exist.
- pd.errors.EmptyDataError: If the file is empty.
- '''
- try:
- if file_type == 'xlsx':
- return pd.read_excel(file_path, **kwargs)
- elif file_type == 'csv':
- return pd.read_csv(file_path, **kwargs)
- except Exception as e:
- logging.error(f"Error reading data from {file_path}: {e}")
- raise
-
-
-def read_data(country: str, is_conflict: bool = False, base_path: str = "../data/processed") -> tuple:
- '''
- Load all data for a given country.
-
- Args:
- country (str): Country name.
- is_conflict (bool): Whether to read conflict data.
- base_path (str): Base path to the data directories.
-
- Returns:
- tuple: DataFrames of household, risk and damage, and optionally conflict data.
- '''
- paths = {
- 'household': (Path(base_path) / "household_survey" / f"{country}.csv", 'csv'),
- 'risk_and_damage': (Path(base_path) / "disaster_risk" / f"{country}.xlsx", 'xlsx'),
- 'conflict': (Path(base_path) / "conflict" / f"{country}.xlsx", 'xlsx')
- }
-
- households = read_data_file(*paths['household'])
- risk_and_damage = read_data_file(*paths['risk_and_damage'])
- conflict = read_data_file(*paths['conflict']) if is_conflict else None
-
- return households, risk_and_damage, conflict
diff --git a/unbreakable/data/saver.py b/unbreakable/data/saver.py
deleted file mode 100644
index 76181ee..0000000
--- a/unbreakable/data/saver.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from pathlib import Path
-import pandas as pd
-
-
-def save_households(households: pd.DataFrame, params: dict, random_seed: int):
- '''Save region households data to a CSV file.
-
- Args:
- households (pd.DataFrame): Households data.
- params (dict): A dictionary of parameters.
- random_seed (int): Random seed.
-
- Returns:
- None
- '''
- output_dir = Path(f'../results/{params["country"]}/households/')
- output_dir.mkdir(parents=True, exist_ok=True)
- file_path = output_dir / f'{params["region"]}_{random_seed}.csv'
- households.to_csv(file_path)
diff --git a/unbreakable/example.py b/unbreakable/example.py
new file mode 100644
index 0000000..f0f64ca
--- /dev/null
+++ b/unbreakable/example.py
@@ -0,0 +1,46 @@
+from unbreakable.experiments.config_handler import load_config, update_config
+from unbreakable.experiments.model_setup import setup_model
+from unbreakable.experiments.experiment_runner import run_experiments
+
+from ema_workbench import ema_logging
+
+ema_logging.log_to_stderr(ema_logging.INFO)
+
+
+def main():
+ try:
+ country = "Example"
+ disaster_spec = [
+ {"type": "flood", "event_time": 0, "return_period": None},
+ # {"type": "flood", "event_time": 0, "return_period": 50},
+ # {"type": "earthquake", "event_time": 0, "return_period": 100},
+ ]
+
+ if len(disaster_spec) == 1:
+ return_period = disaster_spec[0]["return_period"]
+ else:
+ return_period = None
+
+ config = load_config(country)
+ config = update_config(config, disaster_spec)
+ model = setup_model(config)
+
+ experimental_setup = {
+ "country": country,
+ "disaster_spec": disaster_spec,
+ "model": model,
+ "return_period": return_period,
+ "n_scenarios": 1000, # number of replications
+ "n_policies": 0,
+ "multiprocessing": False, # use multiprocessing
+ "n_processes": 16, # number of replications to run in parallel
+ }
+
+ run_experiments(experimental_setup)
+
+ except Exception as e:
+ print(f"An error occurred: {e}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/experiments/__init__.py b/unbreakable/experiments/__init__.py
similarity index 100%
rename from experiments/__init__.py
rename to unbreakable/experiments/__init__.py
diff --git a/unbreakable/experiments/config_handler.py b/unbreakable/experiments/config_handler.py
new file mode 100644
index 0000000..822ce2d
--- /dev/null
+++ b/unbreakable/experiments/config_handler.py
@@ -0,0 +1,146 @@
+import yaml
+from pathlib import Path
+from typing import Dict, Any, Union, List, Set
+
+
+def load_config(country: str) -> Dict[str, Any]:
+ """
+ Load and validate configuration settings for the analysis.
+
+ Args:
+ country (str): Country name.
+
+ Returns:
+ Dict[str, Any]: Validated configuration settings.
+ """
+ config_path = Path(f"../config/{country}.yaml")
+ if not config_path.exists():
+ raise FileNotFoundError(f"Config file for {country} not found at {config_path}")
+
+ with open(config_path, "r") as file:
+ config = yaml.safe_load(file)
+
+ validate_config(config)
+ return config
+
+
+def validate_config(config: Dict[str, Any]) -> None:
+ """Validate the configuration parameters."""
+ required_params = {
+ "constants": {
+ "country": None,
+ "spatial_units": None,
+ "economic_params": {
+ "average_productivity",
+ "income_and_expenditure_growth",
+ "consumption_utility",
+ "discount_rate",
+ },
+ "recovery_params": {
+ "use_precomputed_reconstruction_rates",
+ "lambda_increment",
+ "max_years",
+ },
+ "disaster_params": {
+ "impact_data_type": None,
+ "disaster_impact_params": {
+ "add_income_loss",
+ "poverty_bias_factor",
+ "distribution",
+ "max_bias",
+ "min_bias",
+ },
+ "determine_affected_params": {
+ "loss_margin_pct",
+ "max_random_threshold",
+ "min_random_threshold",
+ "num_simulations",
+ },
+ },
+ "income_params": {"estimate", "randomize", "distribution", "delta"},
+ "savings_params": {
+ "estimate",
+ "randomize",
+ "cap_with_max_savings_rate",
+ "distribution",
+ "delta",
+ "max_savings_rate",
+ },
+ "rent_params": {
+ "estimate",
+ "randomize",
+ "distribution",
+ "pct_of_income",
+ "delta",
+ },
+ "dwelling_vulnerability_params": {
+ "randomize",
+ "distribution",
+ "low",
+ "high",
+ "min_threshold",
+ "max_threshold",
+ },
+ "min_households": None,
+ "atol": None,
+ "analysis_params": {
+ "save_households",
+ "save_consumption_recovery",
+ "distributional_impacts",
+ },
+ }
+ }
+
+ for key, sub_params in required_params.items():
+ if key not in config:
+ raise ValueError(f"Top-level key '{key}' not found in configuration.")
+
+ if sub_params:
+ validate_sub_params(config[key], sub_params, key)
+
+
+def validate_sub_params(
+ config_section: Dict[str, Any],
+ required_params: Dict[str, Union[None, List, Set]],
+ parent_key: str,
+) -> None:
+ """Validate sub-parameters of a configuration section."""
+ for sub_key, expected_values in required_params.items():
+ if sub_key not in config_section:
+ raise ValueError(f"Sub-parameter '{sub_key}' not found in '{parent_key}'.")
+
+ if isinstance(expected_values, (list, set)):
+ validate_value(
+ config_section[sub_key], expected_values, f"{parent_key}.{sub_key}"
+ )
+
+
+def validate_value(
+ value: Any, expected_values: Union[List, Set], param_path: str
+) -> None:
+ """Validate a single configuration value."""
+ if isinstance(expected_values, set):
+ missing_keys = expected_values - set(value.keys())
+ if missing_keys:
+ raise ValueError(f"Missing keys {missing_keys} in {param_path}.")
+ elif value not in expected_values:
+ raise ValueError(
+ f"Value '{value}' for {param_path} not in valid list {expected_values}."
+ )
+
+
+def update_config(config, disaster_spec):
+ """Update the configuration settings with the disaster specification."""
+ config["constants"].update(
+ {
+ "disaster_spec": disaster_spec,
+ }
+ )
+
+ # Event time cannot be greater than years to recover
+ for event in disaster_spec:
+ if event["event_time"] > config["constants"]["recovery_params"]["max_years"]:
+ raise ValueError(
+ f"Event time {event['event_time']} is greater than years to recover {config['constants']['years_to_recover']}"
+ )
+ return config
diff --git a/unbreakable/experiments/experiment_results_formatter.py b/unbreakable/experiments/experiment_results_formatter.py
new file mode 100644
index 0000000..93d55d0
--- /dev/null
+++ b/unbreakable/experiments/experiment_results_formatter.py
@@ -0,0 +1,124 @@
+import pandas as pd
+import numpy as np
+import json
+import ast
+from typing import Tuple, List, Dict, Any
+
+
+def format_experiment_results(
+ results: Tuple[pd.DataFrame, Dict[str, np.ndarray]],
+ include_policies: bool = True,
+ include_uncertainties: bool = True,
+) -> pd.DataFrame:
+ """
+ Process experiment results from EMA Workbench format into a structured DataFrame.
+
+ Args:
+ results (Tuple[pd.DataFrame, Dict[str, np.ndarray]]): EMA Workbench experiment results.
+ include_policies (bool): Whether to include policy values in the output.
+ include_uncertainties (bool): Whether to include uncertainty values in the output.
+
+ Returns:
+ pd.DataFrame: Processed results as a structured DataFrame.
+ """
+ experiments, outcome_data = results
+ outcome_names = load_outcome_names()
+
+ base_columns = ["scenario", "policy", "spatial_unit", "random_seed"]
+ policy_names = ["current_policy"]
+ uncertainty_names = [] # Add uncertainty names if needed
+
+ columns = build_column_list(
+ base_columns,
+ policy_names,
+ uncertainty_names,
+ outcome_names,
+ include_policies,
+ include_uncertainties,
+ )
+
+ processed_data = []
+ for spatial_unit, spatial_unit_outcomes in outcome_data.items():
+ spatial_unit_data = process_spatial_unit_data(
+ experiments,
+ spatial_unit_outcomes,
+ spatial_unit,
+ policy_names,
+ uncertainty_names,
+ outcome_names,
+ include_policies,
+ include_uncertainties,
+ )
+ processed_data.extend(spatial_unit_data)
+
+ results_df = pd.DataFrame(processed_data, columns=columns)
+ return results_df
+
+
+def load_outcome_names() -> List[str]:
+ """Load outcome names from JSON file."""
+ with open("../../unbreakable/experiments/outcome_names_ordered.json", "r") as f:
+ return json.load(f)
+
+
+def build_column_list(
+ base_columns: List[str],
+ policy_names: List[str],
+ uncertainty_names: List[str],
+ outcome_names: List[str],
+ include_policies: bool,
+ include_uncertainties: bool,
+) -> List[str]:
+ """Build the list of columns for the output DataFrame."""
+ columns = base_columns.copy()
+ if include_policies:
+ columns.extend(policy_names)
+ if include_uncertainties:
+ columns.extend(uncertainty_names)
+ columns.extend(outcome_names)
+ return columns
+
+
+def process_spatial_unit_data(
+ experiments: pd.DataFrame,
+ spatial_unit_outcomes: np.ndarray,
+ spatial_unit: str,
+ policy_names: List[str],
+ uncertainty_names: List[str],
+ outcome_names: List[str],
+ include_policies: bool,
+ include_uncertainties: bool,
+) -> List[List[Any]]:
+ """Process data for a single spatial unit."""
+ spatial_unit_data = []
+ for idx, outcome_array in enumerate(spatial_unit_outcomes):
+ row = [
+ experiments["scenario"].iloc[idx],
+ experiments["policy"].iloc[idx],
+ spatial_unit,
+ experiments["random_seed"].iloc[idx],
+ ]
+
+ if include_policies:
+ row.extend(experiments[policy_names].iloc[idx].tolist())
+
+ if include_uncertainties:
+ row.extend(experiments[uncertainty_names].iloc[idx].tolist())
+
+ row.extend(process_outcome_values(outcome_array, outcome_names))
+ spatial_unit_data.append(row)
+
+ return spatial_unit_data
+
+
+def process_outcome_values(
+ outcome_array: np.ndarray, outcome_names: List[str]
+) -> List[Any]:
+ """Process individual outcome values."""
+ processed_values = []
+ for value, name in zip(outcome_array, outcome_names):
+ if name in ["years_in_poverty"]:
+ processed_values.append(ast.literal_eval(value))
+ else:
+ processed_values.append(value)
+ return processed_values
diff --git a/unbreakable/experiments/experiment_runner.py b/unbreakable/experiments/experiment_runner.py
new file mode 100644
index 0000000..8a37364
--- /dev/null
+++ b/unbreakable/experiments/experiment_runner.py
@@ -0,0 +1,47 @@
+from pathlib import Path
+from typing import Dict, Any
+from ema_workbench import perform_experiments, MultiprocessingEvaluator, save_results
+
+
+def run_experiments(experimental_setup: Dict[str, Any]) -> None:
+ """
+ Run experiments with the specified setup using EMA Workbench and save the results.
+
+ Args:
+ experimental_setup (Dict[str, Any]): A dictionary containing the setup for the experiments.
+ """
+ country = experimental_setup["country"]
+ disaster_spec = experimental_setup["disaster_spec"]
+ model = experimental_setup["model"]
+ return_period = experimental_setup["return_period"]
+ n_scenarios = experimental_setup["n_scenarios"]
+ n_policies = experimental_setup["n_policies"]
+ multiprocessing = experimental_setup["multiprocessing"]
+ n_processes = experimental_setup["n_processes"]
+
+ if multiprocessing:
+ with MultiprocessingEvaluator(model, n_processes=n_processes) as evaluator:
+ results = evaluator.perform_experiments(
+ scenarios=n_scenarios, policies=n_policies
+ )
+ else:
+ results = perform_experiments(
+ models=model, scenarios=n_scenarios, policies=n_policies
+ )
+
+ # If disaster spec has only one disaster, extract the disaster type
+ if len(disaster_spec) == 1:
+ disaster_type = disaster_spec[0]["type"]
+
+ # Else, make a combined disaster type
+ else:
+ disaster_type = ""
+ for i in range(len(disaster_spec)):
+ disaster_type += disaster_spec[i]["type"]
+ if i != len(disaster_spec) - 1:
+ disaster_type += "_and_"
+
+ results_path = Path(f"../results/{country}")
+ results_path.mkdir(parents=True, exist_ok=True)
+ filename = f"disaster_type={disaster_type}_return_period={return_period}_scenarios={n_scenarios}_policies={n_policies}.tar.gz"
+ save_results(results, results_path / filename)
diff --git a/unbreakable/experiments/model_setup.py b/unbreakable/experiments/model_setup.py
new file mode 100644
index 0000000..105755f
--- /dev/null
+++ b/unbreakable/experiments/model_setup.py
@@ -0,0 +1,39 @@
+from typing import Dict, Any
+from ema_workbench import Model
+from ema_workbench.em_framework.parameters import (
+ IntegerParameter,
+ CategoricalParameter,
+ Constant,
+)
+from ema_workbench.em_framework.outcomes import ArrayOutcome
+from unbreakable.model import model
+
+
+def setup_model(config: Dict[str, Any]) -> Model:
+ """
+ Set up the EMA Workbench model based on the provided configuration.
+
+ Args:
+ config (Dict[str, Any]): Configuration dictionary loaded from the YAML file.
+
+ Returns:
+ Model: Configured EMA Workbench model.
+ """
+ my_model = Model(name="model", function=model)
+
+ constants = config.get("constants", {})
+ levers = config.get("levers", {})
+
+ # Define seed as an uncertainty for multiple runs,
+ # By specifying a wider range, we want to ensure that the seed is likely to be different for each run
+ my_model.uncertainties = [IntegerParameter("random_seed", 0, 1_000_000_000)]
+ my_model.constants = [Constant(key, value) for key, value in constants.items()]
+ my_model.levers = [CategoricalParameter("current_policy", list(levers.values()))]
+
+ # Outcomes are stored in array and calculated for each region
+ my_model.outcomes = [
+ ArrayOutcome(spatial_unit)
+ for spatial_unit in constants.get("spatial_units", [])
+ ]
+
+ return my_model
diff --git a/unbreakable/experiments/outcome_names_ordered.json b/unbreakable/experiments/outcome_names_ordered.json
new file mode 100644
index 0000000..df94ee5
--- /dev/null
+++ b/unbreakable/experiments/outcome_names_ordered.json
@@ -0,0 +1 @@
+["affected_households_count", "people_count", "affected_people_count", "initial_poor_count", "new_poor_count", "affected_poor_count", "initial_poverty_gap", "updated_initial_poverty_gap", "overall_poverty_gap", "resilience_consumption_based", "resilience_wellbeing_based", "annual_average_consumption_loss", "annual_average_consumption_loss_pct", "average_years_to_recover", "poverty_duration_0", "poverty_duration_1", "poverty_duration_2", "poverty_duration_3", "poverty_duration_4", "poverty_duration_5", "poverty_duration_6", "poverty_duration_7", "poverty_duration_8", "poverty_duration_9", "poverty_duration_10", "annual_average_consumption_loss_pct_female_headed_False", "average_consumption_loss_pct_difference_female_headed_False", "average_reconstruction_rate_female_headed_False", "average_reconstruction_rate_difference_female_headed_False", "r_consumption_based_female_headed_False", "r_consumption_based_difference_female_headed_False", "r_wellbeing_based_female_headed_False", "r_wellbeing_based_difference_female_headed_False", "annual_average_consumption_loss_pct_female_headed_True", "average_consumption_loss_pct_difference_female_headed_True", "average_reconstruction_rate_female_headed_True", "average_reconstruction_rate_difference_female_headed_True", "r_consumption_based_female_headed_True", "r_consumption_based_difference_female_headed_True", "r_wellbeing_based_female_headed_True", "r_wellbeing_based_difference_female_headed_True", "annual_average_consumption_loss_pct_urban_Urban", "average_consumption_loss_pct_difference_urban_Urban", "average_reconstruction_rate_urban_Urban", "average_reconstruction_rate_difference_urban_Urban", "r_consumption_based_urban_Urban", "r_consumption_based_difference_urban_Urban", "r_wellbeing_based_urban_Urban", "r_wellbeing_based_difference_urban_Urban", "annual_average_consumption_loss_pct_urban_Rural", "average_consumption_loss_pct_difference_urban_Rural", "average_reconstruction_rate_urban_Rural", "average_reconstruction_rate_difference_urban_Rural", "r_consumption_based_urban_Rural", "r_consumption_based_difference_urban_Rural", "r_wellbeing_based_urban_Rural", "r_wellbeing_based_difference_urban_Rural", "annual_average_consumption_loss_pct_educat4_highest_Primary (complete or incomplete)", "average_consumption_loss_pct_difference_educat4_highest_Primary (complete or incomplete)", "average_reconstruction_rate_educat4_highest_Primary (complete or incomplete)", "average_reconstruction_rate_difference_educat4_highest_Primary (complete or incomplete)", "r_consumption_based_educat4_highest_Primary (complete or incomplete)", "r_consumption_based_difference_educat4_highest_Primary (complete or incomplete)", "r_wellbeing_based_educat4_highest_Primary (complete or incomplete)", "r_wellbeing_based_difference_educat4_highest_Primary (complete or incomplete)", "annual_average_consumption_loss_pct_educat4_highest_Secondary (complete or incomplete)", "average_consumption_loss_pct_difference_educat4_highest_Secondary (complete or incomplete)", "average_reconstruction_rate_educat4_highest_Secondary (complete or incomplete)", "average_reconstruction_rate_difference_educat4_highest_Secondary (complete or incomplete)", "r_consumption_based_educat4_highest_Secondary (complete or incomplete)", "r_consumption_based_difference_educat4_highest_Secondary (complete or incomplete)", "r_wellbeing_based_educat4_highest_Secondary (complete or incomplete)", "r_wellbeing_based_difference_educat4_highest_Secondary (complete or incomplete)", "annual_average_consumption_loss_pct_educat4_highest_Tertiary (complete or incomplete)", "average_consumption_loss_pct_difference_educat4_highest_Tertiary (complete or incomplete)", "average_reconstruction_rate_educat4_highest_Tertiary (complete or incomplete)", "average_reconstruction_rate_difference_educat4_highest_Tertiary (complete or incomplete)", "r_consumption_based_educat4_highest_Tertiary (complete or incomplete)", "r_consumption_based_difference_educat4_highest_Tertiary (complete or incomplete)", "r_wellbeing_based_educat4_highest_Tertiary (complete or incomplete)", "r_wellbeing_based_difference_educat4_highest_Tertiary (complete or incomplete)", "annual_average_consumption_loss_pct_educat4_highest_No education", "average_consumption_loss_pct_difference_educat4_highest_No education", "average_reconstruction_rate_educat4_highest_No education", "average_reconstruction_rate_difference_educat4_highest_No education", "r_consumption_based_educat4_highest_No education", "r_consumption_based_difference_educat4_highest_No education", "r_wellbeing_based_educat4_highest_No education", "r_wellbeing_based_difference_educat4_highest_No education", "annual_average_consumption_loss_pct_employed_fraction_0.5", "average_consumption_loss_pct_difference_employed_fraction_0.5", "average_reconstruction_rate_employed_fraction_0.5", "average_reconstruction_rate_difference_employed_fraction_0.5", "r_consumption_based_employed_fraction_0.5", "r_consumption_based_difference_employed_fraction_0.5", "r_wellbeing_based_employed_fraction_0.5", "r_wellbeing_based_difference_employed_fraction_0.5", "annual_average_consumption_loss_pct_employed_fraction_0.25", "average_consumption_loss_pct_difference_employed_fraction_0.25", "average_reconstruction_rate_employed_fraction_0.25", "average_reconstruction_rate_difference_employed_fraction_0.25", "r_consumption_based_employed_fraction_0.25", "r_consumption_based_difference_employed_fraction_0.25", "r_wellbeing_based_employed_fraction_0.25", "r_wellbeing_based_difference_employed_fraction_0.25", "annual_average_consumption_loss_pct_employed_fraction_0.2", "average_consumption_loss_pct_difference_employed_fraction_0.2", "average_reconstruction_rate_employed_fraction_0.2", "average_reconstruction_rate_difference_employed_fraction_0.2", "r_consumption_based_employed_fraction_0.2", "r_consumption_based_difference_employed_fraction_0.2", "r_wellbeing_based_employed_fraction_0.2", "r_wellbeing_based_difference_employed_fraction_0.2", "annual_average_consumption_loss_pct_employed_fraction_0.1666666666666666", "average_consumption_loss_pct_difference_employed_fraction_0.1666666666666666", "average_reconstruction_rate_employed_fraction_0.1666666666666666", "average_reconstruction_rate_difference_employed_fraction_0.1666666666666666", "r_consumption_based_employed_fraction_0.1666666666666666", "r_consumption_based_difference_employed_fraction_0.1666666666666666", "r_wellbeing_based_employed_fraction_0.1666666666666666", "r_wellbeing_based_difference_employed_fraction_0.1666666666666666", "annual_average_consumption_loss_pct_employed_fraction_0.6666666666666666", "average_consumption_loss_pct_difference_employed_fraction_0.6666666666666666", "average_reconstruction_rate_employed_fraction_0.6666666666666666", "average_reconstruction_rate_difference_employed_fraction_0.6666666666666666", "r_consumption_based_employed_fraction_0.6666666666666666", "r_consumption_based_difference_employed_fraction_0.6666666666666666", "r_wellbeing_based_employed_fraction_0.6666666666666666", "r_wellbeing_based_difference_employed_fraction_0.6666666666666666", "annual_average_consumption_loss_pct_employed_fraction_0.4", "average_consumption_loss_pct_difference_employed_fraction_0.4", "average_reconstruction_rate_employed_fraction_0.4", "average_reconstruction_rate_difference_employed_fraction_0.4", "r_consumption_based_employed_fraction_0.4", "r_consumption_based_difference_employed_fraction_0.4", "r_wellbeing_based_employed_fraction_0.4", "r_wellbeing_based_difference_employed_fraction_0.4", "annual_average_consumption_loss_pct_employed_fraction_0.3333333333333333", "average_consumption_loss_pct_difference_employed_fraction_0.3333333333333333", "average_reconstruction_rate_employed_fraction_0.3333333333333333", "average_reconstruction_rate_difference_employed_fraction_0.3333333333333333", "r_consumption_based_employed_fraction_0.3333333333333333", "r_consumption_based_difference_employed_fraction_0.3333333333333333", "r_wellbeing_based_employed_fraction_0.3333333333333333", "r_wellbeing_based_difference_employed_fraction_0.3333333333333333", "annual_average_consumption_loss_pct_employed_fraction_0.1428571428571428", "average_consumption_loss_pct_difference_employed_fraction_0.1428571428571428", "average_reconstruction_rate_employed_fraction_0.1428571428571428", "average_reconstruction_rate_difference_employed_fraction_0.1428571428571428", "r_consumption_based_employed_fraction_0.1428571428571428", "r_consumption_based_difference_employed_fraction_0.1428571428571428", "r_wellbeing_based_employed_fraction_0.1428571428571428", "r_wellbeing_based_difference_employed_fraction_0.1428571428571428", "annual_average_consumption_loss_pct_employed_fraction_0.0", "average_consumption_loss_pct_difference_employed_fraction_0.0", "average_reconstruction_rate_employed_fraction_0.0", "average_reconstruction_rate_difference_employed_fraction_0.0", "r_consumption_based_employed_fraction_0.0", "r_consumption_based_difference_employed_fraction_0.0", "r_wellbeing_based_employed_fraction_0.0", "r_wellbeing_based_difference_employed_fraction_0.0", "annual_average_consumption_loss_pct_employed_fraction_0.2857142857142857", "average_consumption_loss_pct_difference_employed_fraction_0.2857142857142857", "average_reconstruction_rate_employed_fraction_0.2857142857142857", "average_reconstruction_rate_difference_employed_fraction_0.2857142857142857", "r_consumption_based_employed_fraction_0.2857142857142857", "r_consumption_based_difference_employed_fraction_0.2857142857142857", "r_wellbeing_based_employed_fraction_0.2857142857142857", "r_wellbeing_based_difference_employed_fraction_0.2857142857142857", "annual_average_consumption_loss_pct_employed_fraction_0.2222222222222222", "average_consumption_loss_pct_difference_employed_fraction_0.2222222222222222", "average_reconstruction_rate_employed_fraction_0.2222222222222222", "average_reconstruction_rate_difference_employed_fraction_0.2222222222222222", "r_consumption_based_employed_fraction_0.2222222222222222", "r_consumption_based_difference_employed_fraction_0.2222222222222222", "r_wellbeing_based_employed_fraction_0.2222222222222222", "r_wellbeing_based_difference_employed_fraction_0.2222222222222222", "annual_average_consumption_loss_pct_employed_fraction_0.125", "average_consumption_loss_pct_difference_employed_fraction_0.125", "average_reconstruction_rate_employed_fraction_0.125", "average_reconstruction_rate_difference_employed_fraction_0.125", "r_consumption_based_employed_fraction_0.125", "r_consumption_based_difference_employed_fraction_0.125", "r_wellbeing_based_employed_fraction_0.125", "r_wellbeing_based_difference_employed_fraction_0.125", "annual_average_consumption_loss_pct_employed_fraction_0.1818181818181818", "average_consumption_loss_pct_difference_employed_fraction_0.1818181818181818", "average_reconstruction_rate_employed_fraction_0.1818181818181818", "average_reconstruction_rate_difference_employed_fraction_0.1818181818181818", "r_consumption_based_employed_fraction_0.1818181818181818", "r_consumption_based_difference_employed_fraction_0.1818181818181818", "r_wellbeing_based_employed_fraction_0.1818181818181818", "r_wellbeing_based_difference_employed_fraction_0.1818181818181818", "annual_average_consumption_loss_pct_employed_fraction_0.2727272727272727", "average_consumption_loss_pct_difference_employed_fraction_0.2727272727272727", "average_reconstruction_rate_employed_fraction_0.2727272727272727", "average_reconstruction_rate_difference_employed_fraction_0.2727272727272727", "r_consumption_based_employed_fraction_0.2727272727272727", "r_consumption_based_difference_employed_fraction_0.2727272727272727", "r_wellbeing_based_employed_fraction_0.2727272727272727", "r_wellbeing_based_difference_employed_fraction_0.2727272727272727", "annual_average_consumption_loss_pct_employed_fraction_0.3636363636363636", "average_consumption_loss_pct_difference_employed_fraction_0.3636363636363636", "average_reconstruction_rate_employed_fraction_0.3636363636363636", "average_reconstruction_rate_difference_employed_fraction_0.3636363636363636", "r_consumption_based_employed_fraction_0.3636363636363636", "r_consumption_based_difference_employed_fraction_0.3636363636363636", "r_wellbeing_based_employed_fraction_0.3636363636363636", "r_wellbeing_based_difference_employed_fraction_0.3636363636363636", "annual_average_consumption_loss_pct_employed_fraction_0.375", "average_consumption_loss_pct_difference_employed_fraction_0.375", "average_reconstruction_rate_employed_fraction_0.375", "average_reconstruction_rate_difference_employed_fraction_0.375", "r_consumption_based_employed_fraction_0.375", "r_consumption_based_difference_employed_fraction_0.375", "r_wellbeing_based_employed_fraction_0.375", "r_wellbeing_based_difference_employed_fraction_0.375", "annual_average_consumption_loss_pct_employed_fraction_0.3", "average_consumption_loss_pct_difference_employed_fraction_0.3", "average_reconstruction_rate_employed_fraction_0.3", "average_reconstruction_rate_difference_employed_fraction_0.3", "r_consumption_based_employed_fraction_0.3", "r_consumption_based_difference_employed_fraction_0.3", "r_wellbeing_based_employed_fraction_0.3", "r_wellbeing_based_difference_employed_fraction_0.3", "annual_average_consumption_loss_pct_employed_fraction_0.0909090909090909", "average_consumption_loss_pct_difference_employed_fraction_0.0909090909090909", "average_reconstruction_rate_employed_fraction_0.0909090909090909", "average_reconstruction_rate_difference_employed_fraction_0.0909090909090909", "r_consumption_based_employed_fraction_0.0909090909090909", "r_consumption_based_difference_employed_fraction_0.0909090909090909", "r_wellbeing_based_employed_fraction_0.0909090909090909", "r_wellbeing_based_difference_employed_fraction_0.0909090909090909", "annual_average_consumption_loss_pct_employed_fraction_0.4285714285714285", "average_consumption_loss_pct_difference_employed_fraction_0.4285714285714285", "average_reconstruction_rate_employed_fraction_0.4285714285714285", "average_reconstruction_rate_difference_employed_fraction_0.4285714285714285", "r_consumption_based_employed_fraction_0.4285714285714285", "r_consumption_based_difference_employed_fraction_0.4285714285714285", "r_wellbeing_based_employed_fraction_0.4285714285714285", "r_wellbeing_based_difference_employed_fraction_0.4285714285714285", "annual_average_consumption_loss_pct_employed_fraction_0.5714285714285714", "average_consumption_loss_pct_difference_employed_fraction_0.5714285714285714", "average_reconstruction_rate_employed_fraction_0.5714285714285714", "average_reconstruction_rate_difference_employed_fraction_0.5714285714285714", "r_consumption_based_employed_fraction_0.5714285714285714", "r_consumption_based_difference_employed_fraction_0.5714285714285714", "r_wellbeing_based_employed_fraction_0.5714285714285714", "r_wellbeing_based_difference_employed_fraction_0.5714285714285714", "annual_average_consumption_loss_pct_employed_fraction_0.1333333333333333", "average_consumption_loss_pct_difference_employed_fraction_0.1333333333333333", "average_reconstruction_rate_employed_fraction_0.1333333333333333", "average_reconstruction_rate_difference_employed_fraction_0.1333333333333333", "r_consumption_based_employed_fraction_0.1333333333333333", "r_consumption_based_difference_employed_fraction_0.1333333333333333", "r_wellbeing_based_employed_fraction_0.1333333333333333", "r_wellbeing_based_difference_employed_fraction_0.1333333333333333", "annual_average_consumption_loss_pct_employed_fraction_0.75", "average_consumption_loss_pct_difference_employed_fraction_0.75", "average_reconstruction_rate_employed_fraction_0.75", "average_reconstruction_rate_difference_employed_fraction_0.75", "r_consumption_based_employed_fraction_0.75", "r_consumption_based_difference_employed_fraction_0.75", "r_wellbeing_based_employed_fraction_0.75", "r_wellbeing_based_difference_employed_fraction_0.75", "annual_average_consumption_loss_pct_employed_fraction_0.6", "average_consumption_loss_pct_difference_employed_fraction_0.6", "average_reconstruction_rate_employed_fraction_0.6", "average_reconstruction_rate_difference_employed_fraction_0.6", "r_consumption_based_employed_fraction_0.6", "r_consumption_based_difference_employed_fraction_0.6", "r_wellbeing_based_employed_fraction_0.6", "r_wellbeing_based_difference_employed_fraction_0.6", "annual_average_consumption_loss_pct_employed_fraction_0.4166666666666667", "average_consumption_loss_pct_difference_employed_fraction_0.4166666666666667", "average_reconstruction_rate_employed_fraction_0.4166666666666667", "average_reconstruction_rate_difference_employed_fraction_0.4166666666666667", "r_consumption_based_employed_fraction_0.4166666666666667", "r_consumption_based_difference_employed_fraction_0.4166666666666667", "r_wellbeing_based_employed_fraction_0.4166666666666667", "r_wellbeing_based_difference_employed_fraction_0.4166666666666667", "annual_average_consumption_loss_pct_employed_fraction_0.8", "average_consumption_loss_pct_difference_employed_fraction_0.8", "average_reconstruction_rate_employed_fraction_0.8", "average_reconstruction_rate_difference_employed_fraction_0.8", "r_consumption_based_employed_fraction_0.8", "r_consumption_based_difference_employed_fraction_0.8", "r_wellbeing_based_employed_fraction_0.8", "r_wellbeing_based_difference_employed_fraction_0.8", "annual_average_consumption_loss_pct_employed_fraction_0.2307692307692307", "average_consumption_loss_pct_difference_employed_fraction_0.2307692307692307", "average_reconstruction_rate_employed_fraction_0.2307692307692307", "average_reconstruction_rate_difference_employed_fraction_0.2307692307692307", "r_consumption_based_employed_fraction_0.2307692307692307", "r_consumption_based_difference_employed_fraction_0.2307692307692307", "r_wellbeing_based_employed_fraction_0.2307692307692307", "r_wellbeing_based_difference_employed_fraction_0.2307692307692307", "annual_average_consumption_loss_pct_employed_fraction_1.0", "average_consumption_loss_pct_difference_employed_fraction_1.0", "average_reconstruction_rate_employed_fraction_1.0", "average_reconstruction_rate_difference_employed_fraction_1.0", "r_consumption_based_employed_fraction_1.0", "r_consumption_based_difference_employed_fraction_1.0", "r_wellbeing_based_employed_fraction_1.0", "r_wellbeing_based_difference_employed_fraction_1.0", "annual_average_consumption_loss_pct_employed_fraction_0.1", "average_consumption_loss_pct_difference_employed_fraction_0.1", "average_reconstruction_rate_employed_fraction_0.1", "average_reconstruction_rate_difference_employed_fraction_0.1", "r_consumption_based_employed_fraction_0.1", "r_consumption_based_difference_employed_fraction_0.1", "r_wellbeing_based_employed_fraction_0.1", "r_wellbeing_based_difference_employed_fraction_0.1", "annual_average_consumption_loss_pct_employed_fraction_0.4444444444444444", "average_consumption_loss_pct_difference_employed_fraction_0.4444444444444444", "average_reconstruction_rate_employed_fraction_0.4444444444444444", "average_reconstruction_rate_difference_employed_fraction_0.4444444444444444", "r_consumption_based_employed_fraction_0.4444444444444444", "r_consumption_based_difference_employed_fraction_0.4444444444444444", "r_wellbeing_based_employed_fraction_0.4444444444444444", "r_wellbeing_based_difference_employed_fraction_0.4444444444444444", "annual_average_consumption_loss_pct_employed_fraction_0.7142857142857143", "average_consumption_loss_pct_difference_employed_fraction_0.7142857142857143", "average_reconstruction_rate_employed_fraction_0.7142857142857143", "average_reconstruction_rate_difference_employed_fraction_0.7142857142857143", "r_consumption_based_employed_fraction_0.7142857142857143", "r_consumption_based_difference_employed_fraction_0.7142857142857143", "r_wellbeing_based_employed_fraction_0.7142857142857143", "r_wellbeing_based_difference_employed_fraction_0.7142857142857143", "annual_average_consumption_loss_pct_employed_fraction_0.2142857142857142", "average_consumption_loss_pct_difference_employed_fraction_0.2142857142857142", "average_reconstruction_rate_employed_fraction_0.2142857142857142", "average_reconstruction_rate_difference_employed_fraction_0.2142857142857142", "r_consumption_based_employed_fraction_0.2142857142857142", "r_consumption_based_difference_employed_fraction_0.2142857142857142", "r_wellbeing_based_employed_fraction_0.2142857142857142", "r_wellbeing_based_difference_employed_fraction_0.2142857142857142", "annual_average_consumption_loss_pct_employed_fraction_0.0833333333333333", "average_consumption_loss_pct_difference_employed_fraction_0.0833333333333333", "average_reconstruction_rate_employed_fraction_0.0833333333333333", "average_reconstruction_rate_difference_employed_fraction_0.0833333333333333", "r_consumption_based_employed_fraction_0.0833333333333333", "r_consumption_based_difference_employed_fraction_0.0833333333333333", "r_wellbeing_based_employed_fraction_0.0833333333333333", "r_wellbeing_based_difference_employed_fraction_0.0833333333333333", "annual_average_consumption_loss_pct_employed_fraction_0.2666666666666666", "average_consumption_loss_pct_difference_employed_fraction_0.2666666666666666", "average_reconstruction_rate_employed_fraction_0.2666666666666666", "average_reconstruction_rate_difference_employed_fraction_0.2666666666666666", "r_consumption_based_employed_fraction_0.2666666666666666", "r_consumption_based_difference_employed_fraction_0.2666666666666666", "r_wellbeing_based_employed_fraction_0.2666666666666666", "r_wellbeing_based_difference_employed_fraction_0.2666666666666666", "annual_average_consumption_loss_pct_employed_fraction_0.0714285714285714", "average_consumption_loss_pct_difference_employed_fraction_0.0714285714285714", "average_reconstruction_rate_employed_fraction_0.0714285714285714", "average_reconstruction_rate_difference_employed_fraction_0.0714285714285714", "r_consumption_based_employed_fraction_0.0714285714285714", "r_consumption_based_difference_employed_fraction_0.0714285714285714", "r_wellbeing_based_employed_fraction_0.0714285714285714", "r_wellbeing_based_difference_employed_fraction_0.0714285714285714", "annual_average_consumption_loss_pct_imp_wat_rec_True", "average_consumption_loss_pct_difference_imp_wat_rec_True", "average_reconstruction_rate_imp_wat_rec_True", "average_reconstruction_rate_difference_imp_wat_rec_True", "r_consumption_based_imp_wat_rec_True", "r_consumption_based_difference_imp_wat_rec_True", "r_wellbeing_based_imp_wat_rec_True", "r_wellbeing_based_difference_imp_wat_rec_True", "annual_average_consumption_loss_pct_imp_wat_rec_False", "average_consumption_loss_pct_difference_imp_wat_rec_False", "average_reconstruction_rate_imp_wat_rec_False", "average_reconstruction_rate_difference_imp_wat_rec_False", "r_consumption_based_imp_wat_rec_False", "r_consumption_based_difference_imp_wat_rec_False", "r_wellbeing_based_imp_wat_rec_False", "r_wellbeing_based_difference_imp_wat_rec_False", "annual_average_consumption_loss_pct_imp_san_rec_True", "average_consumption_loss_pct_difference_imp_san_rec_True", "average_reconstruction_rate_imp_san_rec_True", "average_reconstruction_rate_difference_imp_san_rec_True", "r_consumption_based_imp_san_rec_True", "r_consumption_based_difference_imp_san_rec_True", "r_wellbeing_based_imp_san_rec_True", "r_wellbeing_based_difference_imp_san_rec_True", "annual_average_consumption_loss_pct_imp_san_rec_False", "average_consumption_loss_pct_difference_imp_san_rec_False", "average_reconstruction_rate_imp_san_rec_False", "average_reconstruction_rate_difference_imp_san_rec_False", "r_consumption_based_imp_san_rec_False", "r_consumption_based_difference_imp_san_rec_False", "r_wellbeing_based_imp_san_rec_False", "r_wellbeing_based_difference_imp_san_rec_False", "annual_average_consumption_loss_pct_hsize_ex_5_True", "average_consumption_loss_pct_difference_hsize_ex_5_True", "average_reconstruction_rate_hsize_ex_5_True", "average_reconstruction_rate_difference_hsize_ex_5_True", "r_consumption_based_hsize_ex_5_True", "r_consumption_based_difference_hsize_ex_5_True", "r_wellbeing_based_hsize_ex_5_True", "r_wellbeing_based_difference_hsize_ex_5_True", "annual_average_consumption_loss_pct_hsize_ex_5_False", "average_consumption_loss_pct_difference_hsize_ex_5_False", "average_reconstruction_rate_hsize_ex_5_False", "average_reconstruction_rate_difference_hsize_ex_5_False", "r_consumption_based_hsize_ex_5_False", "r_consumption_based_difference_hsize_ex_5_False", "r_wellbeing_based_hsize_ex_5_False", "r_wellbeing_based_difference_hsize_ex_5_False", "annual_average_consumption_loss_pct_household_has_disability_False", "average_consumption_loss_pct_difference_household_has_disability_False", "average_reconstruction_rate_household_has_disability_False", "average_reconstruction_rate_difference_household_has_disability_False", "r_consumption_based_household_has_disability_False", "r_consumption_based_difference_household_has_disability_False", "r_wellbeing_based_household_has_disability_False", "r_wellbeing_based_difference_household_has_disability_False", "annual_average_consumption_loss_pct_household_has_disability_True", "average_consumption_loss_pct_difference_household_has_disability_True", "average_reconstruction_rate_household_has_disability_True", "average_reconstruction_rate_difference_household_has_disability_True", "r_consumption_based_household_has_disability_True", "r_consumption_based_difference_household_has_disability_True", "r_wellbeing_based_household_has_disability_True", "r_wellbeing_based_difference_household_has_disability_True", "annual_average_consumption_loss_pct_is_single_parent_False", "average_consumption_loss_pct_difference_is_single_parent_False", "average_reconstruction_rate_is_single_parent_False", "average_reconstruction_rate_difference_is_single_parent_False", "r_consumption_based_is_single_parent_False", "r_consumption_based_difference_is_single_parent_False", "r_wellbeing_based_is_single_parent_False", "r_wellbeing_based_difference_is_single_parent_False", "annual_average_consumption_loss_pct_is_single_parent_True", "average_consumption_loss_pct_difference_is_single_parent_True", "average_reconstruction_rate_is_single_parent_True", "average_reconstruction_rate_difference_is_single_parent_True", "r_consumption_based_is_single_parent_True", "r_consumption_based_difference_is_single_parent_True", "r_wellbeing_based_is_single_parent_True", "r_wellbeing_based_difference_is_single_parent_True", "annual_average_consumption_loss_pct_dependency_ratio_High", "average_consumption_loss_pct_difference_dependency_ratio_High", "average_reconstruction_rate_dependency_ratio_High", "average_reconstruction_rate_difference_dependency_ratio_High", "r_consumption_based_dependency_ratio_High", "r_consumption_based_difference_dependency_ratio_High", "r_wellbeing_based_dependency_ratio_High", "r_wellbeing_based_difference_dependency_ratio_High", "annual_average_consumption_loss_pct_dependency_ratio_Low", "average_consumption_loss_pct_difference_dependency_ratio_Low", "average_reconstruction_rate_dependency_ratio_Low", "average_reconstruction_rate_difference_dependency_ratio_Low", "r_consumption_based_dependency_ratio_Low", "r_consumption_based_difference_dependency_ratio_Low", "r_wellbeing_based_dependency_ratio_Low", "r_wellbeing_based_difference_dependency_ratio_Low"]
\ No newline at end of file
diff --git a/unbreakable/main.py b/unbreakable/main.py
new file mode 100644
index 0000000..d07666e
--- /dev/null
+++ b/unbreakable/main.py
@@ -0,0 +1,46 @@
+from unbreakable.experiments.config_handler import load_config, update_config
+from unbreakable.experiments.model_setup import setup_model
+from unbreakable.experiments.experiment_runner import run_experiments
+
+from ema_workbench import ema_logging
+
+ema_logging.log_to_stderr(ema_logging.INFO)
+
+
+def main():
+ try:
+ country = "Bangladesh"
+ disaster_spec = [
+ {"type": "flood", "event_time": 0, "return_period": None},
+ # {"type": "flood", "event_time": 0, "return_period": 50},
+ # {"type": "earthquake", "event_time": 0, "return_period": 100},
+ ]
+
+ if len(disaster_spec) == 1:
+ return_period = disaster_spec[0]["return_period"]
+ else:
+ return_period = None
+
+ config = load_config(country)
+ config = update_config(config, disaster_spec)
+ model = setup_model(config)
+
+ experimental_setup = {
+ "country": country,
+ "disaster_spec": disaster_spec,
+ "model": model,
+ "return_period": return_period,
+ "n_scenarios": 2,
+ "n_policies": 0,
+ "multiprocessing": False,
+ "n_processes": 16,
+ }
+
+ run_experiments(experimental_setup)
+
+ except Exception as e:
+ print(f"An error occurred: {e}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/unbreakable/model.py b/unbreakable/model.py
index 015c64f..7eb25bc 100644
--- a/unbreakable/model.py
+++ b/unbreakable/model.py
@@ -1,57 +1,218 @@
import numpy as np
-from ema_workbench import *
-from unbreakable.data.saver import *
-from unbreakable.data.reader import *
-from unbreakable.data.randomizer import *
-from unbreakable.analysis.calculator import *
-from unbreakable.modules.disaster import *
-from unbreakable.modules.households import *
-from unbreakable.modules.policy import *
-from unbreakable.modules.recovery import *
+import pandas as pd
+from typing import Dict, Any, Optional
+
+from unbreakable.utils.data_loader import load_data, load_reconstruction_rates
+from unbreakable.utils.household_data_preprocessor import prepare_household_data
+from unbreakable.utils.data_randomizer import randomize_dwelling_vulnerability
+from unbreakable.modules.dwelling_vulnerability import calculate_dwelling_vulnerability
+from unbreakable.modules.disaster_impact import (
+ calculate_compound_impact,
+ calculate_years_until_next_event,
+ distribute_disaster_impact,
+ determine_affected_households,
+ split_households_by_affected_percentage,
+)
+from unbreakable.modules.household_recovery import (
+ calculate_household_reconstruction_rates,
+)
+from unbreakable.modules.socioeconomic_impact import estimate_socioeconomic_impact
+from unbreakable.analysis.metric_calculator import calculate_metrics
def model(**params) -> dict:
- '''Simulation model.
+ random_seed = params["random_seed"]
+
+ # ------------------------- 1: Load and prepare data ------------------------- #
+ params["current_policy"] = params.get("current_policy", "none")
+ households, disaster_impacts = load_data(params)
+ reconstruction_rates = load_reconstruction_rates(params)
+ households = prepare_household_data(
+ households, disaster_impacts, params, random_seed
+ )
+
+ # ------- 2: If compound events/multiple events update disaster impacts ------ #
+ disaster_impacts = calculate_compound_impact(
+ params["disaster_spec"], disaster_impacts
+ )
+ years_until_next_event = calculate_years_until_next_event(disaster_impacts, params)
+
+ # ----------------- 3: Simulate disaster in each spatial unit ---------------- #
+ outcomes = {}
+ for spatial_unit in params["spatial_units"]:
+ previous_disaster_type = None
+ spatial_unit_households = households[
+ households["spatial_unit"] == spatial_unit
+ ].copy()
+
+ # In case of multiple events keep track of cumulative impact
+ spatial_unit_households["cumulative_asset_impact_ratio"] = 0
+ spatial_unit_households["ever_affected"] = False
+
+ # -------------------- 4: Iterate over each disaster event ------------------- #
+ for event_time, current_impact in disaster_impacts.items():
+ spatial_unit_households = simulate_disaster(
+ spatial_unit_households,
+ current_impact[current_impact["spatial_unit"] == spatial_unit],
+ previous_disaster_type,
+ params,
+ reconstruction_rates,
+ random_seed,
+ )
+
+ # Store the disaster type for the next event
+ previous_disaster_type = current_impact[
+ current_impact["spatial_unit"] == spatial_unit
+ ]["disaster_type"].values[0]
+
+ # ----------------------- 5. Apply policy interventions ---------------------- #
+ # Note that adaptive social protection policies can be applied here
+ # But retrofitting policies should be applied before the disaster event
+
+ # --------------- 6. Estimate consumption and well-being losses -------------- #
+ spatial_unit_households = estimate_socioeconomic_impact(
+ spatial_unit_households,
+ params,
+ years_until_next_event[event_time],
+ current_impact["disaster_type"].values[0],
+ (
+ current_impact["rp"].iloc[0]
+ if "rp" in current_impact.columns and not current_impact.empty
+ else None
+ ),
+ random_seed,
+ )
+
+ # Update cumulative impact
+ spatial_unit_households[
+ "cumulative_asset_impact_ratio"
+ ] += spatial_unit_households["asset_impact_ratio"]
+ spatial_unit_households["ever_affected"] |= spatial_unit_households[
+ "is_affected"
+ ]
+ # Reset affected status for next event
+ spatial_unit_households["is_affected"] = False
+
+ # ---------------- 7. Calculate outcomes for each spatial unit --------------- #
+ outcomes[spatial_unit] = np.array(
+ list(
+ calculate_metrics(
+ spatial_unit_households,
+ params["recovery_params"]["max_years"],
+ params["analysis_params"],
+ ).values()
+ )
+ )
+
+ return outcomes
+
+
+def simulate_disaster(
+ households: pd.DataFrame,
+ disaster_impact: Dict[str, Any],
+ previous_disaster_type: str,
+ params: Dict[str, Any],
+ reconstruction_rates: Optional[pd.DataFrame] = None,
+ random_seed: int = None,
+) -> pd.DataFrame:
+ """Simulate disaster impact and recovery for a single event.
+
+ This function simulates the impact of a disaster on households and estimates subsequent
+ recovery. It handles different types of disasters and can use either percentage of
+ population affected or Probable Maximum Loss (PML) to determine the disaster's impact.
Args:
- params (dict): A dictionary of parameters. For a complete list of parameters, see, e.g., `config/Nigeria.yaml`.
+ households (pd.DataFrame): DataFrame containing household data.
+ disaster_impact (Dict[str, Any]): Dictionary containing disaster impact information.
+ Must include 'disaster_type' and either 'pct_population_affected' or 'pml'.
+ previous_disaster_type (str): The type of the previous disaster, used to determine
+ if dwelling vulnerability should be randomized.
+ params (Dict[str, Any]): Dictionary containing various simulation parameters.
+ Must include 'dwelling_vulnerability_params', 'disaster_params', 'economic_params',
+ and 'recovery_params'.
+ precomputed_rates (Optional[pd.DataFrame], optional): Precomputed reconstruction rates.
+ If None, rates will be calculated. Defaults to None.
+ random_seed (int, optional): Seed for random number generation to ensure
+ reproducibility. Defaults to None.
Returns:
- dict: A dictionary of outcomes. The key is a district and value is a list of outcomes.
- '''
- random_seed = params['random_seed']
+ pd.DataFrame: Updated household data after simulating disaster impact and initial recovery.
- households, risk_and_damage, conflict = read_data(
- params['country'], params['is_conflict'])
+ Raises:
+ KeyError: If required keys are missing in the input dictionaries.
+ ValueError: If neither 'pct_population_affected' nor 'pml' is provided in disaster_impact.
- households = randomize(
- households, risk_and_damage, params, random_seed)
+ Note:
+ - The function modifies the input households DataFrame in-place.
+ - The function assumes the existence of several helper functions like
+ calculate_dwelling_vulnerability, randomize_dwelling_vulnerability, etc.
+ - The disaster impact is distributed either based on percentage of population
+ affected or PML, depending on which is provided in the disaster_impact dict.
+ """
+ # Extract disaster impact information
+ disaster_type = disaster_impact["disaster_type"].values[0]
- # ! What is this?
- welfare = calculate_welfare(households, params['cons_util'])
+ # Two options are possible for the impact data type:
+ # 'assets', then we have pml or 'population' then we have pct_population_affected
+ pml = disaster_impact.get("pml", pd.Series([None])).iloc[0]
+ pct_population_affected = disaster_impact.get(
+ "pct_population_affected", pd.Series([None])
+ ).iloc[0]
- # Store outcomes in a dict, where key is a region and value is a list of outcomes
- outcomes = {}
+ # If the disaster type has changed, randomize the dwelling vulnerability
+ if previous_disaster_type is None or previous_disaster_type != disaster_type:
+ params["dwelling_vulnerability_params"]["randomize"] = True
+ else:
+ params["dwelling_vulnerability_params"]["randomize"] = False
+
+ # 1: Calculate dwelling vulnerability given the disaster type and randomize if needed
+ households = households.pipe(calculate_dwelling_vulnerability, disaster_type).pipe(
+ randomize_dwelling_vulnerability,
+ params["dwelling_vulnerability_params"],
+ random_seed,
+ )
- for region in params['regions']:
- region_households = households[households['region'] == region].copy(
+ # 2.1: If impact data type is population,
+ # distribute disaster impact based on percentage of population affected
+ if pct_population_affected is not None:
+ unaffected, affected = split_households_by_affected_percentage(
+ households, pct_population_affected
)
- total_exposed_stock, expected_loss_fraction, region_pml = get_region_damage(
- risk_and_damage, region, params['return_period'])
+ affected = distribute_disaster_impact(
+ affected,
+ params["disaster_params"]["disaster_impact_params"],
+ params["dwelling_vulnerability_params"],
+ pml,
+ pct_population_affected,
+ random_seed,
+ )
- region_households = (region_households
- .pipe(calculate_exposure, region_pml, params['pov_bias'], params['calc_exposure_params'])
- .pipe(identify_affected, region_pml, params['identify_aff_params'], random_seed=random_seed)
- .pipe(apply_policy, params['country'], params.get('current_policy', 'none'), params['disaster_type'], random_seed=random_seed)
- .pipe(calculate_recovery_rate, params['avg_prod'], params['cons_util'], params['disc_rate'], params['lambda_incr'], params['yrs_to_rec'], params['is_conflict'], conflict)
- .pipe(calculate_wellbeing, params['avg_prod'], params['cons_util'], params['disc_rate'], params['inc_exp_growth'], params['yrs_to_rec'], params['add_inc_loss'], params['save_consumption_recovery'], params['is_conflict']))
+ households = pd.concat([unaffected, affected])
- if params['save_households']:
- save_households(
- params['country'], region, region_households, random_seed)
+ # 2.2: If impact data type is assets, distribute disaster impact based on PML
+ else:
+ households = households.pipe(
+ distribute_disaster_impact,
+ params["disaster_params"]["disaster_impact_params"],
+ params["dwelling_vulnerability_params"],
+ pml,
+ pct_population_affected,
+ random_seed,
+ ).pipe(
+ determine_affected_households,
+ pml,
+ params["disaster_params"]["determine_affected_params"],
+ random_seed,
+ )
- outcomes[region] = np.array(list(calculate_outcomes(
- region_households, total_exposed_stock, expected_loss_fraction, region_pml, params['yrs_to_rec'], welfare).values()))
+ # 3: Calculate/reuse precomputed household reconstruction rates
+ households = calculate_household_reconstruction_rates(
+ households,
+ params["economic_params"],
+ params["recovery_params"],
+ params["recovery_params"]["use_precomputed_reconstruction_rates"],
+ reconstruction_rates,
+ )
- return outcomes
+ return households
diff --git a/unbreakable/modules/disaster.py b/unbreakable/modules/disaster.py
deleted file mode 100644
index 9e82915..0000000
--- a/unbreakable/modules/disaster.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import pandas as pd
-
-
-def get_region_damage(all_damage: pd.DataFrame, region: str, return_period: int) -> tuple[float, float, float]:
- '''
- Extracts total exposed stock, loss fraction and PML for a given region and return period.
-
- Args:
- all_damage (pd.DataFrame): DataFrame containing damage data.
- region (str): The region to filter the data.
- return_period (int): The return period to filter the data.
-
- Returns:
- tuple[float, float]: A tuple containing the total exposed stock, loss fraction and PML.
- '''
-
- # If the data has `rp` column, use it to filter the data
- if 'rp' in all_damage.columns:
- filtered_data = all_damage.loc[
- (all_damage['region'] == region) & (
- all_damage['rp'] == return_period),
- ['total_exposed_stock', 'loss_fraction', 'pml']
- ]
- # If the doesn't have `rp` column use only the `region` column to filter the data
- else:
- filtered_data = all_damage.loc[
- all_damage['region'] == region,
- ['total_exposed_stock', 'loss_fraction', 'pml']
- ]
-
- if filtered_data.empty:
- raise ValueError(
- "No data found for the specified region and/or return period.")
-
- return tuple(filtered_data.values[0])
diff --git a/unbreakable/modules/disaster_impact.py b/unbreakable/modules/disaster_impact.py
new file mode 100644
index 0000000..a750c07
--- /dev/null
+++ b/unbreakable/modules/disaster_impact.py
@@ -0,0 +1,339 @@
+import pandas as pd
+import numpy as np
+from collections import defaultdict
+from typing import Dict, Union, Tuple
+
+
+def split_households_by_affected_percentage(
+ households: pd.DataFrame, affected_percentage: float
+) -> Tuple[pd.DataFrame, pd.DataFrame]:
+ """
+ Split the households DataFrame into affected and unaffected based on the given percentage.
+
+ Args:
+ households (pd.DataFrame): Original households DataFrame.
+ affected_percentage (float): Percentage of population affected (0 to 1).
+
+ Returns:
+ Tuple[pd.DataFrame, pd.DataFrame]: Unaffected households, Affected households
+ """
+
+ # Calculate the new weights
+ households["unaffected_weight"] = households["household_weight"] * (
+ 1 - affected_percentage
+ )
+ households["affected_weight"] = households["household_weight"] * affected_percentage
+
+ # Create the unaffected DataFrame
+ unaffected = households.copy()
+ unaffected["household_weight"] = unaffected["unaffected_weight"]
+
+ # Create the affected DataFrame
+ affected = households.copy()
+ affected["household_weight"] = affected["affected_weight"]
+
+ # Drop the temporary columns
+ unaffected = unaffected.drop(["unaffected_weight", "affected_weight"], axis=1)
+ affected = affected.drop(["unaffected_weight", "affected_weight"], axis=1)
+
+ # Add a column to indicate affected status
+ affected["is_affected"] = True
+ unaffected["is_affected"] = False
+
+ return unaffected, affected
+
+
+def distribute_disaster_impact(
+ households: pd.DataFrame,
+ disaster_impact_params: Dict[str, Union[str, float, int]],
+ dwelling_vulnerability_params: Dict[str, Union[float, int]],
+ pml: float = None,
+ pct_population_affected: float = None,
+ random_seed: int = None,
+) -> pd.DataFrame:
+ """
+ Distribute disaster impact among households based on either PML or affected percentage.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data.
+ disaster_impact_params (Dict[str, Union[str, float, int]]): Parameters for disaster impact.
+ dwelling_vulnerability_params (Dict[str, Union[float, int]]): Parameters for dwelling vulnerability.
+ pml (float, optional): Probable Maximum Loss. Defaults to None.
+ pct_population_affected (float, optional): Percentage of affected population. Defaults to None.
+ random_seed (int, optional): Random seed for reproducibility. Defaults to None.
+ Returns:
+ pd.DataFrame: Updated households DataFrame with distributed impact.
+
+ Raises:
+ ValueError: If neither PML nor pct_population_affected is provided, or if an unsupported distribution is specified.
+ """
+ if pml is None and pct_population_affected is None:
+ raise ValueError("Either PML or pct_population_affected must be provided.")
+
+ np.random.seed(random_seed)
+
+ if pct_population_affected is not None:
+ # Define how vulnerability can change
+ # Decrease by 0-80%
+ min_change = 0.2
+ max_change = 1.0
+
+ households["vulnerability_change_factor"] = np.random.uniform(
+ min_change, max_change, size=len(households)
+ )
+
+ # Save original v
+ households["v_orig"] = households["v"].copy()
+
+ # Disaster increases vulnerability
+ households["v"] *= households["vulnerability_change_factor"]
+
+ # Ensure that the vulnerability is within the specified thresholds
+ max_threshold = dwelling_vulnerability_params.get("max_threshold", 0.9)
+ min_threshold = dwelling_vulnerability_params.get("min_threshold", 0.2)
+ households["v"] = np.clip(households["v"], min_threshold, max_threshold)
+
+ # No need to calculate asset impact ratio
+ households["asset_impact_ratio"] = None
+
+ else:
+ # Use the original approach with PML
+ poverty_bias_factor = disaster_impact_params.get("poverty_bias_factor", 1.0)
+
+ if poverty_bias_factor == "random":
+ if disaster_impact_params.get("distribution", "uniform") == "uniform":
+ min_bias = disaster_impact_params.get("min_bias", 0.5)
+ max_bias = disaster_impact_params.get("max_bias", 1.5)
+ poverty_bias_factor = np.random.uniform(min_bias, max_bias)
+ else:
+ raise ValueError("Only uniform distribution is supported.")
+
+ households["poverty_bias_factor"] = np.where(
+ households["is_poor"], poverty_bias_factor, 1.0
+ )
+
+ total_weighted_vulnerability = (
+ households[["keff", "v", "poverty_bias_factor", "household_weight"]]
+ .prod(axis=1)
+ .sum()
+ )
+
+ households["asset_impact_ratio"] = (
+ pml / total_weighted_vulnerability
+ ) * households["poverty_bias_factor"]
+
+ return households
+
+
+def determine_affected_households(
+ households: pd.DataFrame,
+ pml: float,
+ params: Dict[str, Union[float, int]],
+ random_seed: int,
+) -> pd.DataFrame:
+ """
+ Determine which households are affected by a disaster.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data.
+ pml (float): Probable Maximum Loss.
+ params (Dict[str, Union[float, int]]): Parameters for determination.
+ random_seed (int, optional): Random seed for reproducibility. Defaults to None.
+
+ Returns:
+ pd.DataFrame: Updated households DataFrame with affected status and asset loss.
+
+ Raises:
+ ValueError: If total asset stock is less than PML or if no suitable mask is found.
+ """
+ np.random.seed(random_seed)
+
+ acceptable_loss_margin = pml * params.get("acceptable_loss_margin ", 0.025)
+ total_asset_value = (households["keff"] * households["household_weight"]).sum()
+
+ if total_asset_value < pml:
+ raise ValueError("Total asset stock is less than PML.")
+
+ min_random_threshold = params.get("min_random_threshold", 0)
+ max_random_threshold = params.get("max_random_threshold", 1)
+ num_simulations = params.get("num_simulations", 10000)
+
+ impact_simulations = (
+ np.random.uniform(
+ min_random_threshold,
+ max_random_threshold,
+ (num_simulations, households.shape[0]),
+ )
+ <= households["asset_impact_ratio"].values
+ )
+
+ simulated_losses = (
+ impact_simulations
+ * households[["keff", "v", "household_weight"]].values.prod(axis=1)
+ ).sum(axis=1)
+
+ valid_simulations = (simulated_losses >= pml - acceptable_loss_margin) & (
+ simulated_losses <= pml + acceptable_loss_margin
+ )
+
+ if not np.any(valid_simulations):
+ raise ValueError(
+ f"Cannot find affected households in {num_simulations} simulations."
+ )
+
+ chosen_simulation = impact_simulations[np.argmax(valid_simulations)]
+
+ households["is_affected"] = chosen_simulation
+ households["asset_loss"] = np.where(
+ households["is_affected"],
+ households[["keff", "v", "household_weight"]].prod(axis=1),
+ 0,
+ )
+
+ total_asset_loss = households["asset_loss"].sum()
+ if not (
+ pml - acceptable_loss_margin <= total_asset_loss <= pml + acceptable_loss_margin
+ ):
+ raise ValueError(
+ f"Total asset loss ({total_asset_loss}) is not within the acceptable range."
+ )
+
+ return households
+
+
+def calculate_compound_impact(disaster_spec, disaster_impacts):
+ """
+ Calculate the compound impact of multiple disasters.
+
+ Args:
+ disaster_spec (list): List of dictionaries containing disaster specifications.
+ disaster_impacts (pd.DataFrame): DataFrame containing disaster risk data.
+
+ Returns:
+ dict: Dictionary containing compound disaster impact.
+ """
+ # If disaster_spec len is 1 there are no coinciding disasters, return the disaster_risk as is
+ if len(disaster_spec) == 1:
+ # Disaster impacts have data on multiple return periods
+ # Filter the disaster impacts for the return period in disaster_spec
+ rp = disaster_spec[0].get("return_period")
+ filtered_impacts = disaster_impacts if rp is None else disaster_impacts[disaster_impacts["rp"] == rp]
+ return {disaster_spec[0]["event_time"]: filtered_impacts}
+
+ # Group disasters by event_time
+ event_time_dict = defaultdict(list)
+ for disaster in disaster_spec:
+ event_time_dict[disaster["event_time"]].append(disaster)
+
+ # Filter coinciding events
+ coinciding = {
+ time: disasters
+ for time, disasters in event_time_dict.items()
+ if len(disasters) > 1
+ }
+
+ # Filter individual events
+ individual = {
+ time: disasters
+ for time, disasters in event_time_dict.items()
+ if len(disasters) == 1
+ }
+
+ # Iterate over coinciding disasters and calculate compound impact as a sum of PMLs
+ compound_risk = {}
+ for time, events in coinciding.items():
+ disaster_types = set(event["type"] for event in events)
+ return_periods = [event["return_period"] for event in events]
+ compound_type = "+".join(sorted(disaster_types))
+ compound_return_period = "+".join(sorted(return_periods))
+
+ # Filter relevant risks once
+ relevant_risks = disaster_impacts[
+ (disaster_impacts["disaster_type"].isin(disaster_types))
+ & (disaster_impacts["rp"].isin(return_periods))
+ ]
+
+ # Group by spatial_unit and calculate compound impact
+ compound_impact = (
+ relevant_risks.groupby("spatial_unit")
+ .agg(
+ {
+ "pml": "sum",
+ "loss_fraction": "sum",
+ "residential": "first",
+ "non_residential": "first",
+ "total_exposed_stock": "first",
+ }
+ )
+ .reset_index()
+ )
+
+ # Ensure that loss_fraction is in [0, 1]
+ compound_impact["loss_fraction"] = compound_impact["loss_fraction"].clip(0, 1)
+
+ # Ensure that PML is not greater than total exposed stock
+ compound_impact["pml"] = compound_impact[["pml", "total_exposed_stock"]].min(
+ axis=1
+ )
+
+ # Name compound disaster
+ compound_impact["disaster_type"] = compound_type
+ compound_impact["rp"] = compound_return_period
+
+ # Reorder columns
+ sorted_columns = [
+ "disaster_type",
+ "spatial_unit",
+ "residential",
+ "non_residential",
+ "total_exposed_stock",
+ "rp",
+ "pml",
+ "loss_fraction",
+ ]
+ compound_risk[time] = compound_impact[sorted_columns]
+
+ individual_risk = {}
+ for time, events in individual.items():
+ for event in events:
+ disaster_type = event["type"]
+ return_period = event["return_period"]
+
+ current_risk = disaster_impacts[
+ (disaster_impacts["disaster_type"] == disaster_type)
+ & (disaster_impacts["rp"] == return_period)
+ ].copy()
+
+ individual_risk[time] = current_risk
+
+ # Combine individual and compound risk dicts
+ combined_risk = {**individual_risk, **compound_risk}
+
+ # Sort combined risk by event time (its keys)
+ combined_risk = dict(sorted(combined_risk.items()))
+
+ return combined_risk
+
+
+def calculate_years_until_next_event(disaster_impacts, params):
+ """Calculate the time until the next event."""
+ # Initialize a new dictionary to store the time until the next event
+ time_until_next_event = {}
+ sorted_times = sorted(disaster_impacts.keys())
+
+ # If there is only one event, return max_years
+ if len(disaster_impacts) == 1:
+ return {sorted_times[0]: params["recovery_params"]["max_years"]}
+
+ # Iterate through the sorted keys and calculate the difference
+ for i in range(len(sorted_times) - 1):
+ current_time = sorted_times[i]
+ next_time = sorted_times[i + 1]
+ time_until_next_event[current_time] = next_time - current_time
+
+ # Handle the last event, which has no next event
+ max_years = params["recovery_params"]["max_years"]
+ time_until_next_event[sorted_times[-1]] = (
+ max_years - time_until_next_event[sorted_times[-2]]
+ )
+ return time_until_next_event
diff --git a/unbreakable/modules/dwelling_vulnerability.py b/unbreakable/modules/dwelling_vulnerability.py
new file mode 100644
index 0000000..ed0700b
--- /dev/null
+++ b/unbreakable/modules/dwelling_vulnerability.py
@@ -0,0 +1,147 @@
+import pandas as pd
+from typing import Dict, Literal
+
+ROOF_SCORES: Dict[str, float] = {
+ "Concrete": 0.2,
+ "Finished – Concrete": 0.2,
+ "Finished – Metal": 0.4,
+ "Finished – Tile": 0.4, # TODO: Confirm this value
+ "Tile": 0.5,
+ "Shingle (asphalt)": 0.5,
+ "Shingle (other)": 0.5,
+ "Finished – Asbestos": 0.6,
+ "Shingle (wood)": 0.6,
+ "Finished – Wood": 0.6, # TODO: Confirm this value
+ "Sheet metal (galvanize, galvalume)": 0.65,
+ "Makeshift/thatched": 0.8,
+ "Natural – Thatch/palm leaf": 0.8,
+ "Other": 0.8,
+}
+
+WALL_SCORES: Dict[str, float] = {
+ "Concrete/Concrete blocks": 0.2,
+ "Concrete/Concrete Blocks": 0.2,
+ "Finished – Cement blocks": 0.3,
+ "Brick/Blocks": 0.35,
+ "Wood & Concrete": 0.4,
+ "Finished – Stone with lime/cement": 0.45,
+ "Finished – GRC/Gypsum/Asbestos": 0.5,
+ "Wood/Timber": 0.6,
+ "Finished – Wood planks/shingles": 0.6, # TODO: Confirm this value
+ "Natural – Other": 0.6,
+ "Plywood": 0.7,
+ "Rudimentary – Plywood": 0.7,
+ "Rudimentary – Other": 0.7, # TODO: Confirm this value
+ "Rudimentary – Uncovered adobe": 0.75, # TODO: Confirm this value
+ "Natural – Cane/palm/trunks": 0.75, # TODO: Confirm this value
+ "Makeshift": 0.8,
+ "Makeshift": 0.8,
+ "Other": 0.8,
+}
+
+FLOOR_SCORES: Dict[str, float] = {
+ "Finished – Cement/red bricks": 0.2,
+ "Finished – Parquet or polished wood": 0.4,
+ "Rudimentary – Wood planks": 0.5,
+ "Natural – Earth/sand": 0.7,
+ "Other": 0.6,
+}
+
+DISASTER_MULTIPLIERS = {
+ "hurricane": {"roof": 0.6, "walls": 0.3, "floor": 0.1},
+ "earthquake": {"roof": 0.2, "walls": 0.6, "floor": 0.2},
+ "flood": {"roof": 0.2, "walls": 0.4, "floor": 0.4},
+}
+
+
+def calculate_dwelling_vulnerability(
+ households: pd.DataFrame, disaster_type: str
+) -> pd.DataFrame:
+ """
+ Calculate dwelling vulnerability based on roof and wall types for a given disaster type.
+ If floor data is available, it will be included in the calculation.
+
+ Args:
+ households (pd.DataFrame): Households DataFrame with 'walls' and 'roof' columns. 'floor' column is optional.
+ disaster_type (str): Type of disaster ('hurricane', 'earthquake', or 'flood').
+
+ Returns:
+ pd.DataFrame: DataFrame with added vulnerability columns.
+
+ Raises:
+ ValueError: If an unsupported disaster type is provided or if there are missing scores for wall or roof types.
+ """
+ # ! ASSUMPTION
+ # If material type is not found in the scores, it is assumed to be 'Other'
+ # Note that 'Other' is the most vulnerable material type
+
+ # Calculate vulnerability scores for walls and roofs
+ households["v_walls"] = (
+ households["walls"].map(WALL_SCORES).fillna(WALL_SCORES["Other"])
+ )
+ households["v_roof"] = (
+ households["roof"].map(ROOF_SCORES).fillna(ROOF_SCORES["Other"])
+ )
+
+ # Check if floor data is available
+ floor_data_available = "floor" in households.columns
+
+ if floor_data_available:
+ households["v_floor"] = (
+ households["floor"].map(FLOOR_SCORES).fillna(FLOOR_SCORES["Other"])
+ )
+
+ # Check for any missing scores
+ missing_wall_types = households[households["v_walls"].isnull()]["walls"].unique()
+ missing_roof_types = households[households["v_roof"].isnull()]["roof"].unique()
+
+ missing_types_message = (
+ f"Missing scores for wall types: {missing_wall_types} "
+ f"and roof types: {missing_roof_types}"
+ )
+
+ if floor_data_available:
+ missing_floor_types = households[households["v_floor"].isnull()][
+ "floor"
+ ].unique()
+ missing_types_message += f" and floor types: {missing_floor_types}"
+
+ if (
+ missing_wall_types.size > 0
+ or missing_roof_types.size > 0
+ or (floor_data_available and missing_floor_types.size > 0)
+ ):
+ raise ValueError(missing_types_message)
+
+ # Get multipliers for the given disaster type
+ try:
+ if "+" in disaster_type:
+ disaster_types = disaster_type.split("+")
+ multipliers = {
+ key: max(
+ DISASTER_MULTIPLIERS[disaster_type][key]
+ for disaster_type in disaster_types
+ )
+ for key in ["walls", "roof", "floor"]
+ }
+ else:
+ multipliers = DISASTER_MULTIPLIERS[disaster_type]
+ except KeyError:
+ raise ValueError(f"Disaster type '{disaster_type}' not supported")
+
+ # Calculate initial vulnerability
+ if floor_data_available:
+ households["v_init"] = (
+ households["v_walls"] * multipliers["walls"]
+ + households["v_roof"] * multipliers["roof"]
+ + households["v_floor"] * multipliers["floor"]
+ )
+ else:
+ # Adjust the calculation if floor data is not available
+ total_weight = multipliers["walls"] + multipliers["roof"]
+ households["v_init"] = (
+ households["v_walls"] * multipliers["walls"]
+ + households["v_roof"] * multipliers["roof"]
+ ) / total_weight
+
+ return households
diff --git a/unbreakable/modules/household_recovery.py b/unbreakable/modules/household_recovery.py
new file mode 100644
index 0000000..b581dbc
--- /dev/null
+++ b/unbreakable/modules/household_recovery.py
@@ -0,0 +1,217 @@
+import pandas as pd
+import numpy as np
+from typing import Dict, Optional
+
+
+def calculate_household_reconstruction_rates(
+ households: pd.DataFrame,
+ economic_params: Dict[str, float],
+ recovery_params: Dict[str, float],
+ use_precomputed_reconstruction_rates: bool = False,
+ reconstruction_rates: Optional[pd.DataFrame] = None,
+) -> pd.DataFrame:
+ """
+ Calculate reconstruction rates for affected households.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data.
+ economic_params (Dict[str, float]): Economic parameters for reconstruction calculation.
+ recovery_params (Dict[str, float]): Recovery parameters for reconstruction calculation.
+ use_precomputed_reconstruction_rates (bool): Whether to use precomputed reconstruction rates.
+ reconstruction_rates (Optional[pd.DataFrame]): Precomputed reconstruction rates data for 'population' impact data type.
+
+ Returns:
+ pd.DataFrame: Updated DataFrame with reconstruction rates for affected households.
+
+ Raises:
+ ValueError: If reconstruction rates are invalid or if precomputed rates are missing for 'population' type.
+ """
+ if use_precomputed_reconstruction_rates:
+ if reconstruction_rates is None:
+ raise ValueError(
+ "Precomputed rates data must be provided for 'population' impact data type."
+ )
+
+ households["reconstruction_rate"] = 0.0
+
+ # Identify affected households
+ affected_mask = households["is_affected"]
+
+ # NOTE Precomputed rates are calculated for rounded vulnerability values
+ households.loc[affected_mask, "v_rounded"] = households.loc[
+ affected_mask, "v"
+ ].round(2)
+
+ # Merge precomputed rates only for affected households
+ affected_households = households.loc[affected_mask].merge(
+ reconstruction_rates,
+ left_on="v_rounded",
+ right_on="v",
+ how="left",
+ suffixes=("", "_precomputed"),
+ )
+
+ # Check for missing precomputed rates
+ missing_rates = affected_households["reconstruction_rate_precomputed"].isnull()
+ if missing_rates.any():
+ missing_v = affected_households.loc[missing_rates, "v_rounded"].unique()
+ raise ValueError(
+ f"Precomputed reconstruction rates not found for vulnerability values: {missing_v}"
+ )
+
+ # Update reconstruction rates for affected households
+ households.loc[affected_mask, "reconstruction_rate"] = affected_households[
+ "reconstruction_rate_precomputed"
+ ].values
+
+ # Clean up temporary columns
+ households = households.drop(
+ ["v_rounded", "v_precomputed", "reconstruction_rate_precomputed"],
+ axis=1,
+ errors="ignore",
+ )
+
+ return households
+
+ else:
+ # Original calculation for PML-based approach
+ affected_mask = households["is_affected"]
+ households.loc[affected_mask, "reconstruction_rate"] = 0.0
+ households.loc[affected_mask, "reconstruction_rate"] = households.loc[
+ affected_mask
+ ].apply(
+ lambda row: find_optimal_reconstruction_rate(
+ row["v"], economic_params, recovery_params
+ ),
+ axis=1,
+ )
+
+ # Validate reconstruction rates
+ validate_reconstruction_rates(
+ households.loc[households["is_affected"], "reconstruction_rate"],
+ recovery_params["max_years"],
+ )
+
+ return households
+
+
+def find_optimal_reconstruction_rate(
+ dwelling_vulnerability: float,
+ economic_params: Dict[str, float],
+ recovery_params: Dict[str, float],
+) -> float:
+ """
+ Find the optimal reconstruction rate for a household given its dwelling vulnerability.
+
+ Args:
+ dwelling_vulnerability (float): Dwelling vulnerability score of the household.
+ economic_params (Dict[str, float]): Economic parameters for reconstruction calculation.
+ recovery_params (Dict[str, float]): Recovery parameters for reconstruction calculation.
+
+ Returns:
+ float: Optimal reconstruction rate.
+
+ Notes:
+ This function uses a numerical optimization approach to find the optimal
+ reconstruction rate that maximizes utility over time.
+ """
+ max_years = recovery_params["max_years"]
+ lambda_increment = recovery_params["lambda_increment"]
+ average_productivity = economic_params["average_productivity"]
+ consumption_utility = economic_params["consumption_utility"]
+ discount_rate = economic_params["discount_rate"]
+ total_weeks = 52 * recovery_params["max_years"]
+ dt = 1 / 52
+ lambda_value = 0
+ last_derivative_lambda = 0
+
+ while True:
+ derivative_lambda = 0
+ for time in np.linspace(0, max_years, total_weeks):
+ factor = average_productivity + lambda_value
+ marginal_utility_term = (
+ average_productivity
+ - factor * dwelling_vulnerability * np.exp(-lambda_value * time)
+ ) ** (-consumption_utility)
+ time_productivity_adjustment = time * factor - 1
+ discount_factor = np.exp(-time * (discount_rate + lambda_value))
+ derivative_lambda += (
+ marginal_utility_term
+ * time_productivity_adjustment
+ * discount_factor
+ * dt
+ )
+ if (
+ (last_derivative_lambda < 0 and derivative_lambda > 0)
+ or (last_derivative_lambda > 0 and derivative_lambda < 0)
+ or lambda_value > max_years
+ ):
+ return lambda_value
+ last_derivative_lambda = derivative_lambda
+ lambda_value += lambda_increment
+
+
+def validate_reconstruction_rates(rates: pd.Series, max_years: int) -> None:
+ """
+ Validate the calculated reconstruction rates.
+
+ Args:
+ rates (pd.Series): Series of reconstruction rates.
+ max_years (int): Maximum allowed years for reconstruction.
+
+ Raises:
+ ValueError: If any reconstruction rate is invalid (0 or equal to max_years).
+ """
+ if rates.eq(max_years).any():
+ raise ValueError("Reconstruction rate not found for some households")
+ if rates.eq(0).any():
+ raise ValueError("Reconstruction rate is 0 for some households")
+ if rates.isna().any():
+ raise ValueError("Reconstruction rate is missing for some households")
+
+
+def precompute_reconstruction_rates(
+ economic_params, recovery_params, dwelling_vulnerabilities
+):
+ """Precompute optimal reconstruction rates for a range of dwelling vulnerabilities.
+ Args:
+ economic_params (Dict[str, float]): Economic parameters for reconstruction calculation.
+ recovery_params (Dict[str, float]): Recovery parameters for reconstruction calculation.
+ dwelling_vulnerabilities (np.ndarray): Array of dwelling vulnerabilities.
+ Returns:
+ None
+ """
+ optimal_rates = [
+ find_optimal_reconstruction_rate(v, economic_params, recovery_params)
+ for v in dwelling_vulnerabilities
+ ]
+ optimal_rates_df = pd.DataFrame(
+ {
+ "v": dwelling_vulnerabilities,
+ "reconstruction_rate": optimal_rates,
+ }
+ )
+
+ # Round vulnerabilities to 2 decimal places to ensure 0.01 step
+ optimal_rates_df["v"] = optimal_rates_df["v"].round(2)
+
+ optimal_rates_df.to_csv(
+ "../../data/generated/optimal_reconstruction_rates.csv", index=False
+ )
+
+
+if __name__ == "__main__":
+ # NOTE These are dummy parameters for the sake of the example
+ economic_params = {
+ "average_productivity": 0.25636,
+ "consumption_utility": 1.5,
+ "discount_rate": 0.04,
+ }
+ recovery_params = {"max_years": 10, "lambda_increment": 0.01}
+
+ # Generate vulnerabilities with exact 0.01 step
+ dwelling_vulnerabilities = np.round(np.arange(0.2, 0.91, 0.01), 2)
+
+ precompute_reconstruction_rates(
+ economic_params, recovery_params, dwelling_vulnerabilities
+ )
diff --git a/unbreakable/modules/households.py b/unbreakable/modules/households.py
deleted file mode 100644
index 1a10b20..0000000
--- a/unbreakable/modules/households.py
+++ /dev/null
@@ -1,148 +0,0 @@
-import pandas as pd
-import numpy as np
-
-
-def calculate_exposure(households: pd.DataFrame, region_pml: float, pov_bias: float, calc_exposure_params: dict) -> pd.DataFrame:
- '''Calculate how much each of the households is exposed to the disaster.
-
- Households can be either equally exposed to the disaster or the exposure can be re-distributed between poor and non-poor households with the use of `poverty_bias`.
-
- Args:
- households (pd.DataFrame): Households.
- region_pml (float): Region PML.
- pov_bias (float): Poverty bias.
- calc_exposure_params (dict): Parameters for calculating exposure.
-
- Returns:
- pd.DataFrame: Households with a new `fa` column representing the impact of the disaster.
-
- Raises:
- ValueError: If only uniform distribution is supported yet.
- '''
-
- # Random value for poverty bias
- if pov_bias == 'random':
- if calc_exposure_params['distr'] == 'uniform':
- # default 0.5
- low = calc_exposure_params['low']
- # default 1.5
- high = calc_exposure_params['high']
- poverty_bias = np.random.uniform(low, high)
- else:
- raise ValueError("Only uniform distribution is supported yet.")
- else:
- poverty_bias = pov_bias
-
- # Set poverty bias to 1 for all households
- households['pov_bias'] = 1
-
- # Set poverty bias to povbias for poor households
- households.loc[households['is_poor'] == True, 'pov_bias'] = poverty_bias
-
- # Keff is the effective capital stock of the household
- # Physical assets such as land, housing, and durable goods
- # NOTE: Currently, only the dwelling value k_house is considered
- households['keff'] = households['k_house'].copy()
-
- # How much each household is affected by the disaster
- normalization_factor = households[['keff', 'v', 'pov_bias', 'wgt']].prod(
- axis=1).sum()
-
- # Distribute the impact of the disaster given region's PML across households
- households['fa'] = (region_pml / normalization_factor) * \
- households['pov_bias'] # `Poverty bias` allows to re-distribute impact between poor and non-poor households
-
- return households
-
-
-def identify_affected(households: pd.DataFrame, region_pml: float, ident_affected_params: dict, random_seed: int) -> pd.DataFrame:
- '''Determine affected households.
-
- We assume that all households have the same chance of being affected,
- but based on `fa` value calculated in `calculate_exposure`.
-
- Args:
- households (pd.DataFrame): Households.
- district_pml (float): Region PML.
- ident_affected_params (dict): Parameters for determining affected households function.
-
- Returns:
- pd.DataFrame: Households with `is_affected` and `asset_loss` columns.
-
- Raises:
- ValueError: If no mask was found.
- '''
- # BUG: For whatever reason fixing random seed in the model.py doesn't work here
- if random_seed is not None:
- np.random.seed(random_seed)
-
- # Allow for a relatively small error between the total asset loss and the PML
- delta = region_pml * ident_affected_params['delta_pct'] # default 0.025
-
- # Check if total asset is less than PML
- tot_asset_stock = households[['keff', 'wgt']].prod(axis=1).sum()
- if tot_asset_stock < region_pml:
- raise ValueError(
- 'Total asset stock is less than PML.')
-
- low = ident_affected_params['low'] # default 0
- high = ident_affected_params['high'] # default 1
-
- # Generate multiple boolean masks at once
- num_masks = ident_affected_params['num_masks'] # default 10,000
- masks = np.random.uniform(
- low, high, (num_masks, households.shape[0])) <= households['fa'].values
-
- # Compute total_asset_loss for each mask
- asset_losses = (
- masks * households[['keff', 'v', 'wgt']].values.prod(axis=1)).sum(axis=1)
-
- # Find the first mask that yields a total_asset_loss within the desired range
- mask_index = np.where((asset_losses >= region_pml - delta) &
- (asset_losses <= region_pml + delta))
-
- # Raise an error if no mask was found
- if mask_index is None:
- raise ValueError(
- f'Cannot find affected households in {num_masks} iterations.')
- else:
- try:
- # Select the first mask that satisfies the condition
- mask_index = mask_index[0][0]
- except:
- print('mask_index: ', mask_index)
-
- chosen_mask = masks[mask_index]
-
- # Raise an error if no mask was found
- if len(chosen_mask) == 0:
- raise ValueError(
- f'Cannot find affected households in {num_masks} iterations.')
-
- # Assign the chosen mask to the 'is_affected' column of the DataFrame
- households['is_affected'] = chosen_mask
-
- # Save the asset loss for each household
- households['asset_loss'] = households.loc[households['is_affected'], [
- 'keff', 'v', 'wgt']].prod(axis=1)
- households['asset_loss'] = households['asset_loss'].fillna(0)
-
- # Check whether the total asset loss is within the desired range
- tot_asset_loss = households['asset_loss'].sum()
- if (tot_asset_loss < region_pml - delta) or (tot_asset_loss > region_pml + delta):
- raise ValueError(
- f'Total asset loss ({tot_asset_loss}) is not within the desired range.')
-
- # num_affected = households['is_affected'].sum()
- # print(f'Number of affected households: {num_affected}')
- # print(households[households['is_affected']].index)
-
- return households
-
-
-def calculate_welfare(households: pd.DataFrame, consumption_utility: float) -> float:
- '''Calculate the welfare of all households in a country based on their expenditures and a given consumption utility.'''
- weighted_average_expenditure = np.sum(households['exp'] * households['wgt']) / np.sum(
- households['wgt'])
- welfare = weighted_average_expenditure ** (-consumption_utility)
- return welfare
diff --git a/unbreakable/modules/policy.py b/unbreakable/modules/policy.py
deleted file mode 100644
index ed4254f..0000000
--- a/unbreakable/modules/policy.py
+++ /dev/null
@@ -1,331 +0,0 @@
-import pandas as pd
-import numpy as np
-
-
-def cash_transfer(households: pd.DataFrame, current_policy: str) -> pd.DataFrame:
- '''
- Apply cash transfer to a specific target group.
-
- This function applies a cash transfer policy to a specific target group of households. The policy is specified in the format "+", where can be "all", "poor", "poor_near_poor1.25", or "poor_near_poor2.0", and is a percentage value indicating the amount to be added to the 'sav' column of the households.
-
- Args:
- households (pd.DataFrame): Households.
- Required columns: 'is_affected', 'is_poor', 'exp', 'poverty_line_adjusted', 'keff', 'v', 'sav'
- policy (str): Policy to apply. Format: "+". Example: "poor+100".
-
- Returns:
- pd.DataFrame: Households with applied policy.
- '''
- try:
- target_group, top_up = current_policy.split('+')
- top_up = float(top_up)
- except ValueError:
- raise ValueError(
- "policy should be in the format '+'")
-
- # Get the adjusted poverty line
- poverty_line_adjusted = households['poverty_line_adjusted'].iloc[0]
-
- # Filter affected households
- affected_households = households.query('is_affected')
-
- # Determine beneficiaries based on target group
- if target_group == 'all':
- beneficiaries = affected_households
-
- elif target_group == 'poor':
- beneficiaries = affected_households.query('is_poor')
-
- # If there are no poor households, return the original DataFrame
- if len(beneficiaries) == 0:
- return households
-
- # TODO: Split into separate policies poor and near_poor
- elif target_group in ['poor_near_poor1.25', 'poor_near_poor2.0']:
- multiplier = 1.25 if target_group == 'poor_near_poor1.25' else 2.0
- # Define conditions for poor and near poor households
- poor_condition = affected_households['is_poor'] == True
- near_poor_condition = (~affected_households['is_poor']) & (
- affected_households['exp'] < multiplier * poverty_line_adjusted)
-
- # Combine conditions to identify beneficiaries
- beneficiary_condition = poor_condition | near_poor_condition
-
- # If there are no beneficiaries, return the original DataFrame
- if not beneficiary_condition.any():
- return households
-
- # Select beneficiaries based on the combined condition
- beneficiaries = affected_households.loc[beneficiary_condition]
- else:
- raise ValueError(f"Unknown target group: {target_group}")
-
- # Apply top-up
- households.loc[beneficiaries.index, 'sav'] += (
- beneficiaries.eval('keff*v') * top_up / 100
- )
-
- return households
-
-
-def retrofitting(country: str, households: pd.DataFrame, current_policy: str, disaster_type: str, random_seed: int) -> pd.DataFrame:
- '''
- Apply retrofitting to a specific target group.
-
- This function applies a retrofitting policy to a specific target group of households. The policy is specified in the format "+", where can be "all", "poor_40", and is a percentage value indicating the proportion of houses to be retrofitted.
-
- Args:
- country (str): Country name.
- households (pd.DataFrame): Households.
- Required columns: 'roof', 'walls', 'is_poor', 'exp'
- policy (str): Policy to apply. Format: "+". Example: "poor_40+100".
- disaster_type (str): Type of disaster. Example: "hurricane".
- random_seed (int): Random seed for reproducibility.
-
- Returns:
- pd.DataFrame: Households with applied policy.
-
- Raises:
- ValueError: If the policy format is incorrect or the households DataFrame does not contain the required columns.
- '''
- if random_seed is not None:
- # Set random seed for reproducibility
- np.random.seed(random_seed)
-
- try:
- target_group, houses_pct = current_policy.split('+')
- houses_pct = int(houses_pct)
- except ValueError:
- raise ValueError(
- "my_policy should be in the format '+'")
-
- # Check whether the households DataFrame contains the required columns
- if not {'roof', 'walls', 'is_poor', 'exp'}.issubset(households.columns):
- raise ValueError(
- "Households DataFrame must contain 'roof', 'walls', 'is_poor', and 'exp' columns")
-
- # Each country has different retrofitting policies
- if country == 'Dominica':
- # Define which houses are vulnerable (material vulnerability score > 0.5)
- v_roof_types = [
- 'Shingle (wood)', 'Shingle (asphalt)', 'Shingle (other)', 'Other']
- v_walls_types = ['Wood/Timber', 'Plywood',
- 'Makeshift', "Other/Don't know", 'Other']
- robust_roof = 'Concrete'
- robust_walls = 'Concrete/Concrete blocks'
-
- # Find the vulnerable houses where both roof and walls are vulnerable
- vulnerable_houses = households[households['walls'].isin(
- v_walls_types) | households['roof'].isin(v_roof_types)]
-
- # Select only the ones that own
- vulnerable_houses = vulnerable_houses[vulnerable_houses['own_rent'] == 'own']
-
- if len(vulnerable_houses) == 0:
- return households
-
- # Save old roof and walls materials
- households['roof_old'] = households['roof']
- households['walls_old'] = households['walls']
-
- # Apply the policy to a percentage of the vulnerable houses
- if houses_pct != 100:
- if random_seed is not None:
- # ?: Check if fixing the np random seed affects the sampling
- vulnerable_houses = vulnerable_houses.sample(
- frac=houses_pct/100, random_state=random_seed)
- else:
- vulnerable_houses = vulnerable_houses.sample(
- frac=houses_pct/100)
-
- # Search for poor households if the target group is not 'all'
- if target_group != 'all':
- # Get pct of poor households
- pct_poor = int(target_group.split('_')[1]) / 100
-
- # Find the poor vulnerable houses
- poor_houses = vulnerable_houses.query('is_poor')
-
- # Find pct_poor (e.g., 40%) of the poorest expenditure-wise
- poor_houses = poor_houses.nsmallest(
- int(len(poor_houses) * pct_poor), 'exp', keep='all')
-
- if len(poor_houses) == 0:
- return households
-
- # Keep only the poor houses
- vulnerable_houses = vulnerable_houses.loc[poor_houses. index]
-
- # Apply retrofitting to the vulnerable houses
- households['retrofitted'] = False
-
- # Retrofit roofs
- # current_roofs = households.loc[vulnerable_houses.index, 'roof']
- # current_walls = households.loc[vulnerable_houses.index, 'walls']
-
- households.loc[vulnerable_houses.index, 'roof'] = households.loc[vulnerable_houses.index, 'roof'].apply(
- lambda x: robust_roof if x in v_roof_types else x
- )
- # Retrofit walls
- households.loc[vulnerable_houses.index, 'walls'] = households.loc[vulnerable_houses.index, 'walls'].apply(
- lambda x: robust_walls if x in v_walls_types else x
- )
-
- # retrofitted_roofs = households.loc[vulnerable_houses.index, 'roof']
- # retrofitted_walls = households.loc[vulnerable_houses.index, 'walls']
-
- # Print how many roofs and walls were retrofitted
- # print(
- # f"Retrofitting {len(vulnerable_houses)} houses: {len(vulnerable_houses[retrofitted_roofs != current_roofs])} roofs and {len(vulnerable_houses[retrofitted_walls != current_walls])} walls")
-
- households.loc[vulnerable_houses.index, 'retrofitted'] = True
-
- # Calculate the new vulnerability score
- households = recalculate_house_vulnerability(
- country, households, disaster_type)
-
- # NOTE: After retrofitting we do not randomize the vulnerability score
- return households
-
- else:
- raise ValueError(f"Country '{country}' not yet supported")
-
-
-def recalculate_house_vulnerability(country: str, households: pd.DataFrame, disaster_type: str) -> pd.DataFrame:
- '''Recalculate vulnerability of a house based on its new retrofitted roof and walls material.
-
- Args:
- country (str): Country name.
- households (pd.DataFrame): Households.
- Required columns: 'roof', 'walls'
- disaster_type (str): Type of disaster. Example: "hurricane".
-
- Returns:
- pd.DataFrame: Households with recalculated vulnerability scores.
-
- Raises:
- ValueError: If the country is not supported.
- ValueError: If the disaster type is not supported.
- '''
- # Each country has different roof and wall materials and their respective vulnerability scores
- if country == 'Dominica':
- # Define vulnerability scores in dictionaries for easy mapping
- v_roof_scores = {
- 'Concrete': 0.2,
- 'Sheet metal (galvanize, galvalume)': 0.4,
- 'Shingle (wood)': 0.6,
- 'Shingle (asphalt)': 0.6,
- 'Shingle (other)': 0.6,
- 'Other': 0.75,
- }
-
- v_walls_scores = {
- 'Brick/Blocks': 0.2,
- 'Concrete/Concrete Blocks': 0.2,
- 'Concrete/Concrete blocks': 0.2,
- 'Wood & Concrete': 0.4,
- 'Wood/Timber': 0.6,
- 'Plywood': 0.7,
- 'Makeshift': 0.8,
- "Other/Don't know": 0.8,
- "Other/Don't Know": 0.8,
- 'Other': 0.8,
- }
-
- elif country == 'Nigeria':
- v_roof_scores = {
- 'Finished – Concrete': 0.2,
- 'Finished – Asbestos': 0.25,
- 'Finished – Metal tile': 0.35,
- 'Finished – Tile': 0.5,
- 'Other – Specific': 0.75,
- 'Rudimentary – Other': 0.75,
- 'Other': 0.75,
- 'Natural – Thatch/palm leaf': 0.9
- }
-
- v_walls_scores = {
- 'Finished – Cement blocks': 0.2,
- 'Finished – Stone with lime/cement': 0.4,
- 'Finished – Woven Bamboo': 0.6,
- 'Rudimentary – Bamboo with mud': 0.8,
- 'Other': 0.8,
- }
-
- else:
- raise ValueError(f"Country '{country}' not yet supported")
-
- # Save current vulnerability score
- # current_v = households['v'].copy()
- # current_v_roof = households['v_roof'].copy()
- # current_v_walls = households['v_walls'].copy()
-
- # Calculate the vulnerability scores for the roof and walls
- households['v_roof'] = households['roof'].map(v_roof_scores)
- households['v_walls'] = households['walls'].map(v_walls_scores)
-
- # Count how many v values changed
- # print(
- # f'Changed {len(households[households["v_roof"] != current_v_roof])} roofs')
- # print(
- # f'Changed {len(households[households["v_walls"] != current_v_walls])} walls')
-
- # Calculate the new vulnerability score
- if disaster_type == 'hurricane':
- v_roof_multiplier = 0.6
- v_walls_multiplier = 0.4
- elif disaster_type == 'earthquake':
- v_roof_multiplier = 0.3
- v_walls_multiplier = 0.7
- elif disaster_type == 'flood':
- v_roof_multiplier = 0.2
- v_walls_multiplier = 0.8
- else:
- raise ValueError(f"Disaster type '{disaster_type}' not yet supported")
-
- # NOTE: Since it is for a retrofitting policy,
- # we immediately assign the new values to `v` and not `v_init` column
- households['v'] = v_roof_multiplier * \
- households['v_roof'] + v_walls_multiplier * households['v_walls']
-
- # Assertions to check values are within expected range
- assert households[['v_roof', 'v_walls', 'v']].apply(
- lambda x: (x >= 0).all() and (x <= 1).all()).all()
- assert households['v'].isna().sum() == 0
-
- return households
-
-
-def apply_policy(households: pd.DataFrame, country: str, current_policy: str, disaster_type: str, random_seed: int) -> pd.DataFrame:
- '''
- Apply a specific policy to a set of households.
-
- This function applies a specific policy to a set of households, based on their economic status and the impact of external factors. The policy is specified in the format ":", where can be "asp" (cash transfer) or "retrofit" (housing retrofitting), and is a string containing the details of the policy.
-
- Args:
- country (str): Country name.
- households (pd.DataFrame): Households.
- Required columns: 'is_affected', 'is_poor', 'exp', 'povline_adjusted', 'keff', 'v', 'sav', 'roof', 'walls'
- policy (str): Policy to apply. Format: ":". Example: "asp:poor+100".
- disaster_type (str): Type of disaster. Example: "hurricane".
- random_seed (int): Random seed for reproducibility.
-
- Returns:
- pd.DataFrame: Households with applied policy.
-
- Raises:
- ValueError: If the policy type is unknown.
- '''
- # Identify the type of policy provided
- policy_type = current_policy.split(':')[0]
-
- # Apply the policy based on its type
- if policy_type == 'asp':
- return cash_transfer(households, current_policy.split(':')[1])
- elif policy_type == 'retrofit':
- return retrofitting(country, households, current_policy.split(':')[1], disaster_type, random_seed)
- elif policy_type == 'none':
- return households
- else:
- raise ValueError(
- f"Unknown policy type: {policy_type}, please use 'asp', 'retrofit' or 'none'")
diff --git a/unbreakable/data/__init__.py b/unbreakable/modules/policy_interventions.py
similarity index 100%
rename from unbreakable/data/__init__.py
rename to unbreakable/modules/policy_interventions.py
diff --git a/unbreakable/modules/recovery.py b/unbreakable/modules/recovery.py
deleted file mode 100644
index ae6b5b1..0000000
--- a/unbreakable/modules/recovery.py
+++ /dev/null
@@ -1,213 +0,0 @@
-import numpy as np
-import pandas as pd
-import pickle
-import os
-
-
-def calculate_recovery_rate(households: pd.DataFrame, average_productivity: float, consumption_utility: float, discount_rate: float, lambda_increment: float, years_to_recover: int, is_conflict: bool, conflict: pd.DataFrame = None) -> pd.DataFrame:
- # Assign initial value to recovery_rate
- households['recovery_rate'] = 0
-
- # Subset households that are affected by the disaster
- affected_households = households[households['is_affected'] == True].copy()
-
- # If there is a conflict, adjust the average productivity
- if is_conflict:
- region_conflict_intensity = conflict[conflict['region']
- == households['region'].values[0]]['conflict_intensity'].values[0]
-
- adjusted_average_productivity = {'Very high': 0.225,
- 'High': 0.25,
- 'Medium': 0.275,
- 'Low': 0.3,
- 'Very low': 0.325,
- 'None': 0.35}
- average_productivity = adjusted_average_productivity[region_conflict_intensity]
-
- # Search for the recovery rate for each affected household
- affected_households['recovery_rate'] = affected_households['v'].apply(
- lambda x: find_recovery_rate(x, average_productivity, consumption_utility, discount_rate, lambda_increment, years_to_recover))
-
- assert (affected_households['recovery_rate'] == years_to_recover).any(
- ) == False, 'Recovery rate was not found for one of the households'
- assert (affected_households['recovery_rate'] > 1).any(
- ) == False, 'Recovery rate is greater than 1 for one of the households'
- assert (affected_households['recovery_rate'] == 0).any(
- ) == False, 'Recovery rate is 0 for one of the households'
-
- households.loc[affected_households.index,
- 'recovery_rate'] = affected_households['recovery_rate']
-
- return households
-
-
-def find_recovery_rate(v: float, average_productivity: float, consumption_utility: float, discount_rate: float, lambda_increment: float, years_to_recover: int) -> float:
- totaL_weeks = 52 * years_to_recover
- dt = 1 / 52
-
- lambda_value = 0
- last_derivative_lambda = 0
-
- while True:
- derivative_lambda = 0
- for time in np.linspace(0, years_to_recover, totaL_weeks):
- factor = average_productivity + lambda_value
- part1 = (average_productivity - factor * v *
- np.exp(-lambda_value * time)) ** (-consumption_utility)
- part2 = time * factor - 1
- part3 = np.exp(-time * (discount_rate + lambda_value))
- derivative_lambda += part1 * part2 * part3 * dt
-
- if (last_derivative_lambda < 0 and derivative_lambda > 0) or (last_derivative_lambda > 0 and derivative_lambda < 0) or lambda_value > years_to_recover:
- return lambda_value
-
- last_derivative_lambda = derivative_lambda
- lambda_value += lambda_increment
-
-
-def calculate_wellbeing(households: pd.DataFrame, average_productivity: float, consumption_utility: float, discount_rate: float, income_and_expenditure_growth: float, years_to_recover: int, add_income_loss: bool, save_consumption_recovery: bool, is_conflict: bool = False, conflict: pd.DataFrame = None) -> pd.DataFrame:
-
- # Get the adjusted poverty line for the region
- poverty_line_adjusted = households['poverty_line_adjusted'].values[0]
-
- # Add new columns with initial values
- new_columns = ['consumption_loss', 'consumption_loss_npv', 'net_consumption_loss',
- 'net_consumption_loss_npv', 'c_t', 'c_t_unaffected', 'weeks_in_poverty', 'wellbeing']
- households[new_columns] = 0
-
- # Subset households that are affected by the disaster
- affected_households = households[households['is_affected'] == True].copy()
-
- # Define the number of weeks given the number of years
- totaL_weeks = 52 * years_to_recover
- dt = 1 / 52
-
- consumption_recovery = {}
-
- if is_conflict:
- region_conflict_class = households['conflict_intensity'].values[0]
- marco_multiplier = {'Very high': 0.05,
- 'High': 0.02997,
- 'Medium': 0.0232,
- 'Low': 0.01595,
- 'Very low': 0.00725,
- 'None': 0.0}
- vulnerability_increase_factor = 1 + \
- marco_multiplier[region_conflict_class]
- else:
- vulnerability_increase_factor = 1
-
- # Integrate consumption loss and well-being
- for time in np.linspace(0, years_to_recover, totaL_weeks):
- exponential_multiplier = np.e**(
- -affected_households['recovery_rate'] * time)
-
- growth_factor = (1 + income_and_expenditure_growth)**time
-
- expenditure = growth_factor * affected_households['exp']
-
- savings = growth_factor * \
- affected_households['sav'] * (1 / vulnerability_increase_factor)
-
- asset_loss = growth_factor * \
- affected_households['v'] * affected_households['keff'] * \
- affected_households['recovery_rate'] * \
- vulnerability_increase_factor
-
- income_loss = growth_factor * average_productivity * \
- affected_households['keff'] * \
- affected_households['v'] * vulnerability_increase_factor
-
- # asset_loss = growth_factor * affected_households['v'] * \
- # (affected_households['exp_house'] +
- # affected_households[['keff', 'recovery_rate']].prod(axis=1))
-
- if add_income_loss == False:
- affected_households['c_t'] = (expenditure +
- exponential_multiplier * (savings - asset_loss))
- else:
- affected_households['c_t'] = (expenditure +
- exponential_multiplier * (savings - asset_loss - income_loss))
-
- affected_households['c_t_unaffected'] = expenditure
-
- # Avoid negative consumption
- if (affected_households['c_t'] < 0).any():
- affected_households.loc[affected_households['c_t'] < 0, 'c_t'] = 0
-
- # Make sure that consumption does not exceed the unaffected consumption
- if (affected_households['c_t'] > affected_households['c_t_unaffected']).any():
- affected_households.loc[affected_households['c_t'] > affected_households['c_t_unaffected'],
- 'c_t'] = affected_households.loc[affected_households['c_t'] > affected_households['c_t_unaffected'], 'c_t_unaffected']
-
- # Calculate consumption loss
- affected_households['consumption_loss'] += dt * \
- (affected_households['c_t_unaffected'] -
- affected_households['c_t'])
-
- affected_households['consumption_loss_npv'] += dt * \
- (affected_households['c_t_unaffected'] -
- affected_households['c_t'])*np.e**(-discount_rate*time)
-
- # BUG: That's wrong, if exp_house = 0 then then net_consumption_loss is 0
- affected_households['net_consumption_loss'] += dt * \
- np.e**(-affected_households['recovery_rate']*time) * \
- affected_households['v'] * growth_factor * \
- affected_households['exp_house']
-
- # BUG: That's wrong, if exp_house = 0 then then net_consumption_loss_npv is 0
- affected_households['net_consumption_loss_npv'] += dt * \
- np.e**(-affected_households['recovery_rate']*time) * affected_households['v'] * growth_factor * \
- affected_households['exp_house'] * \
- np.e**(-discount_rate*time)
-
- # Increase the number of weeks in poverty
- affected_households.loc[affected_households['c_t']
- < poverty_line_adjusted, 'weeks_in_poverty'] += 1
-
- # Calculate wellbeing
- affected_households['wellbeing'] += affected_households['c_t_unaffected']**(1 - consumption_utility)\
- / (1 - consumption_utility) * dt \
- * ((1 - ((affected_households['c_t_unaffected'] - affected_households['c_t']) / affected_households['c_t_unaffected'])
- * np.e**(-affected_households['recovery_rate'] * time))**(1 - consumption_utility) - 1)\
- * np.e**(-discount_rate * time)
-
- # Store the consumption recovery for each time step
- if save_consumption_recovery:
- consumption_recovery[time] = affected_households.loc[:, [
- 'wgt', 'is_poor', 'recovery_rate', 'c_t_unaffected', 'c_t']].set_index('wgt')
-
- # Save the content of the columns for affected_households into households data frame
- households.loc[affected_households.index,
- new_columns] = affected_households[new_columns]
-
- # Save consumption recovery as a pickle file
- if save_consumption_recovery:
- country = households['country'].values[0]
- region = households['region'].values[0]
- return_period = households['return_period'].values[0]
- try:
- random_seed = households['random_seed'].values[0]
- except:
- random_seed = None
-
- save_consumption_recovery_to_file(consumption_recovery,
- country, region, return_period, is_conflict, random_seed)
-
- return households
-
-
-def save_consumption_recovery_to_file(consumption_recovery: dict, country: str, region: str, return_period: str, is_conflict: bool, random_seed: int):
- if is_conflict:
- folder = f'../experiments/{country}/consumption_recovery/return_period={return_period}/conflict={is_conflict}/{random_seed}'
- else:
- folder = f'../experiments/{country}/consumption_recovery/return_period={return_period}/conflict={is_conflict}/{random_seed}'
-
- # Create a folder if it does not exist
- if not os.path.exists(folder):
- os.makedirs(folder)
-
- # Save consumption recovery as pickle file
- with open(folder + f'/{region}.pickle', 'wb') as handle:
- pickle.dump(consumption_recovery, handle,
- protocol=pickle.HIGHEST_PROTOCOL)
diff --git a/unbreakable/modules/socioeconomic_impact.py b/unbreakable/modules/socioeconomic_impact.py
new file mode 100644
index 0000000..0d6aa74
--- /dev/null
+++ b/unbreakable/modules/socioeconomic_impact.py
@@ -0,0 +1,399 @@
+import pandas as pd
+import numpy as np
+import os
+import pickle
+from typing import Dict, List
+
+
+def estimate_socioeconomic_impact(
+ households: pd.DataFrame,
+ params: dict,
+ years_until_next_event: int,
+ disaster_type: str,
+ return_period: str = None,
+ random_seed: int = None,
+) -> pd.DataFrame:
+ """
+ Estimate the socioeconomic impact of a disaster on households.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data.
+ params (dict): Dictionary containing economic, disaster impact, and analysis parameters.
+ years_until_next_event (int): Number of years until the next disaster event.
+ disaster_type (str): Type of disaster.
+ return_period (str): Return period of the disaster.
+ random_seed (int): Random seed used in the simulation. Note that nothing is stochastic in this function.
+
+ Returns:
+ pd.DataFrame: Updated household data with estimated socioeconomic impact.
+ """
+ # TODO: Review how the socioeconomic impact is estimated in case of consecutive events
+
+ # Extract parameters
+ economic_params = params["economic_params"]
+ analysis_params = params["analysis_params"]
+ disaster_impact_params = params["disaster_params"]["disaster_impact_params"]
+
+ # Set up constants
+ weeks_in_year = 52
+ dt = 1 / weeks_in_year
+
+ # Use this columns to store cumulative losses across multiple events
+ columns_to_update: List[str] = [
+ "consumption_loss",
+ "consumption_loss_npv",
+ "net_consumption_loss",
+ "net_consumption_loss_npv",
+ "weeks_in_poverty",
+ "wellbeing_loss",
+ ]
+
+ # These columns must be reset to zero for each event
+ columns_to_reset: List[str] = ["c_t", "c_t_unaffected"]
+
+ households = households.copy()
+ households[columns_to_update] = households.get(columns_to_update, 0.0)
+ households[columns_to_reset] = 0.0
+
+ # Filter affected households
+ affected_households = households[households["is_affected"] == True].copy()
+
+ if affected_households.empty:
+ return households
+
+ # Dictionary to store consumption recovery data
+ consumption_recovery = {}
+
+ for t in np.linspace(
+ 0, years_until_next_event, int(years_until_next_event * weeks_in_year)
+ ):
+ update_affected_households(
+ affected_households, t, economic_params, disaster_impact_params, dt
+ )
+
+ if analysis_params["save_consumption_recovery"]:
+ store_consumption_recovery(consumption_recovery, affected_households, t)
+
+ # Update main dataframe
+ households.loc[affected_households.index, columns_to_update + columns_to_reset] = (
+ affected_households[columns_to_update + columns_to_reset]
+ )
+
+ # Save consumption recovery data if required
+ if analysis_params["save_consumption_recovery"]:
+ save_consumption_recovery(
+ consumption_recovery,
+ params["country"],
+ households["spatial_unit"].values[0],
+ disaster_type,
+ return_period,
+ random_seed,
+ )
+
+ return households
+
+
+def update_affected_households(
+ affected_households: pd.DataFrame,
+ t: float,
+ economic_params: dict,
+ disaster_impact_params: dict,
+ dt: float,
+):
+ """
+ Update the affected households' data for a given time step.
+
+ Args:
+ affected_households (pd.DataFrame): DataFrame of affected households.
+ t (float): Current time step.
+ economic_params (dict): Dictionary of economic parameters.
+ disaster_impact_params (dict): Dictionary of disaster impact parameters.
+ dt (float): Time step size.
+ """
+ exponential_multiplier = np.exp(-affected_households["reconstruction_rate"] * t)
+ growth_factor = (1 + economic_params["income_and_expenditure_growth"]) ** t
+
+ expenditure = growth_factor * affected_households["exp"]
+ savings = growth_factor * affected_households["sav"]
+ asset_loss = (
+ growth_factor
+ * affected_households["v"]
+ * affected_households["keff"]
+ * affected_households["reconstruction_rate"]
+ )
+ income_loss = (
+ growth_factor
+ * economic_params["average_productivity"]
+ * affected_households["keff"]
+ * affected_households["v"]
+ )
+
+ if disaster_impact_params["add_income_loss"]:
+ affected_households["c_t"] = expenditure + exponential_multiplier * (
+ savings - asset_loss - income_loss
+ )
+ else:
+ affected_households["c_t"] = expenditure + exponential_multiplier * (
+ savings - asset_loss
+ )
+
+ affected_households["c_t_unaffected"] = expenditure
+
+ # Ensure c_t is at least 1
+ # TODO Review this clipping, maybe it should be 0
+ affected_households["c_t"] = (
+ affected_households[["c_t", "c_t_unaffected"]].min(axis=1).clip(lower=0)
+ )
+
+ update_losses(affected_households, t, economic_params, dt)
+
+
+def update_losses(
+ affected_households: pd.DataFrame, t: float, economic_params: dict, dt: float
+):
+ """
+ Update the losses for affected households.
+
+ Args:
+ affected_households (pd.DataFrame): DataFrame of affected households.
+ t (float): Current time step.
+ economic_params (dict): Dictionary of economic parameters.
+ dt (float): Time step size.
+ """
+ # ! If c_t was larger than c_t_unaffected,
+ # the consumption_loss will be 0
+ # TODO Fix this
+
+ consumption_loss = dt * (
+ affected_households["c_t_unaffected"] - affected_households["c_t"]
+ )
+
+ consumption_loss_npv = consumption_loss * np.exp(
+ -economic_params["discount_rate"] * t
+ )
+
+ affected_households["consumption_loss"] += consumption_loss
+ affected_households["consumption_loss_npv"] += consumption_loss_npv
+
+ net_consumption_loss = (
+ dt
+ * np.exp(-affected_households["reconstruction_rate"] * t)
+ * affected_households["v"]
+ * (1 + economic_params["income_and_expenditure_growth"]) ** t
+ * affected_households["rent"]
+ )
+ net_consumption_loss_npv = net_consumption_loss * np.exp(
+ -economic_params["discount_rate"] * t
+ )
+
+ affected_households["net_consumption_loss"] += net_consumption_loss
+ affected_households["net_consumption_loss_npv"] += net_consumption_loss_npv
+
+ # ! Poverty line is yearly and c_t is weekly
+ affected_households.loc[
+ affected_households["c_t"] < (affected_households["poverty_line"] / 52),
+ "weeks_in_poverty",
+ ] += 1
+
+ update_wellbeing(affected_households, t, economic_params, dt)
+
+
+def update_wellbeing(
+ affected_households: pd.DataFrame, t: float, economic_params: dict, dt: float
+):
+ """
+ Update the wellbeing loss for affected households.
+
+ Args:
+ affected_households (pd.DataFrame): DataFrame of affected households.
+ t (float): Current time step.
+ economic_params (dict): Dictionary of economic parameters.
+ dt (float): Time step size.
+ """
+ unaffected_utility = (
+ affected_households["c_t_unaffected"]
+ ** (1 - economic_params["consumption_utility"])
+ ) / (1 - economic_params["consumption_utility"])
+
+ adjusted_wellbeing = (
+ (
+ 1
+ - (
+ (affected_households["c_t_unaffected"] - affected_households["c_t"])
+ / affected_households["c_t_unaffected"]
+ )
+ * np.exp(-affected_households["reconstruction_rate"] * t)
+ )
+ ** (1 - economic_params["consumption_utility"])
+ ) - 1
+
+ wellbeing_loss = (
+ unaffected_utility
+ * dt
+ * adjusted_wellbeing
+ * np.exp(-economic_params["discount_rate"] * t)
+ )
+
+ # If t = 0, and wellbeing_loss is inf or nan, turn it into 0
+ if t == 0:
+ wellbeing_loss = wellbeing_loss.replace([np.inf, -np.inf], 0).fillna(0)
+
+ affected_households["wellbeing_loss"] += wellbeing_loss
+
+
+def store_consumption_recovery(
+ consumption_recovery: Dict, affected_households: pd.DataFrame, t: float
+):
+ """
+ Store consumption recovery data for a given time step.
+
+ Args:
+ consumption_recovery (Dict): Dictionary to store consumption recovery data.
+ affected_households (pd.DataFrame): DataFrame of affected households.
+ t (float): Current time step.
+ """
+ consumption_recovery[t] = affected_households[
+ [
+ "household_id",
+ "household_weight",
+ "is_poor",
+ "reconstruction_rate",
+ "c_t_unaffected",
+ "c_t",
+ ]
+ ].set_index("household_id")
+
+
+def save_consumption_recovery(
+ consumption_recovery: Dict,
+ country: str,
+ spatial_unit: str,
+ disaster_type: str,
+ return_period: int = None,
+ random_seed: int = None,
+):
+ """
+ Save consumption recovery to a file.
+
+ Args:
+ consumption_recovery (Dict): Dictionary containing consumption recovery data.
+ country (str): Country name.
+ spatial_unit (str): Spatial unit identifier.
+ disaster_type (str): Type of disaster.
+ return_period (int): Return period of the disaster.
+ random_seed (int): Random seed used in the simulation.
+ """
+ folder = f"../results/{country}/consumption_recovery/"
+ os.makedirs(folder, exist_ok=True)
+
+ with open(
+ f"{folder}/{spatial_unit}_{disaster_type}_rp={return_period}_{random_seed}.pickle",
+ "wb",
+ ) as handle:
+ pickle.dump(consumption_recovery, handle, protocol=pickle.HIGHEST_PROTOCOL)
+
+
+# def update_wellbeing(
+# affected_households: pd.DataFrame, t: float, economic_params: dict, dt: float
+# ):
+# """
+# Update the wellbeing loss for affected households with added diagnostic checks.
+
+# Args:
+# affected_households (pd.DataFrame): DataFrame of affected households.
+# t (float): Current time step.
+# economic_params (dict): Dictionary of economic parameters.
+# dt (float): Time step size.
+# """
+# # Check 1: Print input parameters
+# print(f"Time step: {t}, dt: {dt}")
+# print(f"Economic params: {economic_params}")
+
+# # Check 2: Verify c_t_unaffected is positive
+# if (affected_households["c_t_unaffected"] <= 0).any():
+# print("Warning: c_t_unaffected contains non-positive values")
+# print(affected_households[affected_households["c_t_unaffected"] <= 0])
+
+# unaffected_utility = (
+# affected_households["c_t_unaffected"]
+# ** (1 - economic_params["consumption_utility"])
+# ) / (1 - economic_params["consumption_utility"])
+
+# # Check 3: Verify unaffected_utility calculation
+# if np.isinf(unaffected_utility).any() or np.isnan(unaffected_utility).any():
+# print("Warning: unaffected_utility contains inf or nan values")
+# print(
+# affected_households[
+# np.isinf(unaffected_utility) | np.isnan(unaffected_utility)
+# ]
+# )
+
+# relative_consumption_change = (
+# affected_households["c_t_unaffected"] - affected_households["c_t"]
+# ) / affected_households["c_t_unaffected"]
+
+# # Check 4: Verify relative consumption change
+# if (relative_consumption_change >= 1).any() or (
+# relative_consumption_change < 0
+# ).any():
+# print("Warning: relative consumption change is >= 1 or < 0")
+# print(
+# affected_households[
+# (relative_consumption_change >= 1) | (relative_consumption_change < 0)
+# ]
+# )
+
+# reconstruction_term = np.exp(-affected_households["reconstruction_rate"] * t)
+
+# # Check 5: Verify reconstruction term
+# if np.isinf(reconstruction_term).any() or np.isnan(reconstruction_term).any():
+# print("Warning: reconstruction term contains inf or nan values")
+# print(
+# affected_households[
+# np.isinf(reconstruction_term) | np.isnan(reconstruction_term)
+# ]
+# )
+
+# adjusted_wellbeing = (
+# (1 - relative_consumption_change * reconstruction_term)
+# ** (1 - economic_params["consumption_utility"])
+# ) - 1
+
+# # Check 6: Verify adjusted_wellbeing calculation
+# if np.isinf(adjusted_wellbeing).any() or np.isnan(adjusted_wellbeing).any():
+# print("Warning: adjusted_wellbeing contains inf or nan values")
+# print(
+# affected_households[
+# np.isinf(adjusted_wellbeing) | np.isnan(adjusted_wellbeing)
+# ]
+# )
+
+# discount_term = np.exp(-economic_params["discount_rate"] * t)
+
+# wellbeing_loss = unaffected_utility * dt * adjusted_wellbeing * discount_term
+
+# # Check 7: Verify final wellbeing_loss calculation
+# if np.isinf(wellbeing_loss).any() or np.isnan(wellbeing_loss).any():
+# print("Warning: wellbeing_loss contains inf or nan values")
+# print(affected_households[np.isinf(wellbeing_loss) | np.isnan(wellbeing_loss)])
+
+# # If t = 0, and wellbeing_loss is inf or nan, turn it into 0
+# if t == 0:
+# wellbeing_loss = wellbeing_loss.replace([np.inf, -np.inf], 0).fillna(0)
+
+# affected_households["wellbeing_loss"] += wellbeing_loss
+
+# # Check 8: Verify final wellbeing_loss in DataFrame
+# if (
+# np.isinf(affected_households["wellbeing_loss"]).any()
+# or np.isnan(affected_households["wellbeing_loss"]).any()
+# ):
+# print("Warning: Final wellbeing_loss contains inf or nan values")
+# print(
+# affected_households[
+# np.isinf(affected_households["wellbeing_loss"])
+# | np.isnan(affected_households["wellbeing_loss"])
+# ]
+# )
+
+# return affected_households
diff --git a/unbreakable/utils/__init__.py b/unbreakable/utils/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/unbreakable/utils/data_estimator.py b/unbreakable/utils/data_estimator.py
new file mode 100644
index 0000000..e1f3422
--- /dev/null
+++ b/unbreakable/utils/data_estimator.py
@@ -0,0 +1,173 @@
+import pandas as pd
+import numpy as np
+from typing import Optional
+
+
+def estimate_effective_capital_stock(
+ households: pd.DataFrame, params: dict
+) -> pd.DataFrame:
+ """
+ Estimate effective capital stock for homeowners.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data.
+ params (dict): Dictionary of parameters for estimation.
+
+ Returns:
+ pd.DataFrame: DataFrame with estimated capital stock.
+
+ Raises:
+ ValueError: If 'inc' or 'owns_house' columns are not present in the DataFrame.
+ """
+ if "inc" not in households.columns or "owns_house" not in households.columns:
+ raise ValueError(
+ "Both 'inc' and 'owns_house' columns must be present to estimate capital stock."
+ )
+
+ households = households.copy()
+ households.loc[households["owns_house"] == True, "k_house"] = (
+ households["inc"] / params["economic_params"]["average_productivity"]
+ )
+
+ households.loc[households["owns_house"] == False, "k_house"] = 0
+
+ # NOTE
+ # Keff is the effective capital stock of the household
+ # Physical assets such as land, homes, and durable goods used to generate income
+ # For now we assume that keff is equal to the dwelling value k_house
+ households["keff"] = households["k_house"]
+
+ # TODO Estimate effective capital stock for renters in a more realistic way
+ # Estimate effective capital stock for renters based on savings rate
+ savings_rate = (households["inc"] - households["exp"]) / households["inc"]
+
+ households.loc[households["owns_house"] == False, "keff"] = (
+ households["inc"]
+ * savings_rate
+ / params["economic_params"]["average_productivity"]
+ )
+
+ return households
+
+
+def estimate_welfare(households: pd.DataFrame, params: dict) -> pd.DataFrame:
+ """
+ Estimate welfare based on consumption utility function.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data.
+ params (dict): Dictionary of parameters for estimation.
+
+ Returns:
+ pd.DataFrame: DataFrame with estimated welfare.
+
+ Raises:
+ ValueError: If 'exp' column is not present in the DataFrame.
+ """
+ if "exp" not in households.columns:
+ raise ValueError("'exp' column must be present to estimate welfare.")
+
+ households = households.copy()
+
+ # TODO Review the equation since it contradicts with Walsh & Hallegatte (2020)
+ weighted_average_expenditure = np.sum(
+ households["exp"] * households["household_weight"]
+ ) / np.sum(households["household_weight"])
+ welfare = weighted_average_expenditure ** (
+ -params["economic_params"]["consumption_utility"]
+ )
+ households["welfare"] = welfare
+ return households
+
+
+def estimate_rent(households: pd.DataFrame, params: dict) -> pd.DataFrame:
+ """
+ Estimate household rent as percentage of income.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data.
+ params (dict): Dictionary of parameters for estimation.
+
+ Returns:
+ pd.DataFrame: DataFrame with estimated rent.
+
+ Raises:
+ ValueError: If 'inc' column is not present in the DataFrame.
+ """
+ if "inc" not in households.columns:
+ raise ValueError("'inc' column must be present to estimate rent.")
+
+ households = households.copy()
+ pct_of_income = params.get("pct_of_income", 0.3)
+ households["rent"] = households["inc"] * pct_of_income
+ return households
+
+
+def estimate_savings(households: pd.DataFrame, params: dict) -> pd.DataFrame:
+ """
+ Estimate household savings based on income and expenditure.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data.
+ params (dict): Dictionary of parameters for estimation.
+
+ Returns:
+ pd.DataFrame: DataFrame with estimated savings.
+
+ Raises:
+ ValueError: If 'inc' or 'exp' columns are not present in the DataFrame.
+ """
+ if "inc" not in households.columns or "exp" not in households.columns:
+ raise ValueError(
+ "Both 'inc' and 'exp' columns must be present to estimate savings."
+ )
+
+ households = households.copy()
+ if params.get("cap_with_max_savings_rate", False):
+ max_savings_rate = params.get("max_savings_rate", 0.05)
+ households["sav"] = households["inc"] * max_savings_rate
+
+ else:
+ households["sav"] = households["inc"] - households["exp"]
+ return households
+
+
+def estimate_income(households: pd.DataFrame, params: dict) -> pd.DataFrame:
+ """
+ Estimate household incomes based on expenditure and income-to-expenditure ratios.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data.
+ params (dict): Dictionary of parameters for estimation.
+
+ Returns:
+ pd.DataFrame: DataFrame with estimated incomes.
+
+ Raises:
+ ValueError: If no income-to-expenditure ratio is found or provided.
+ """
+ households = households.copy()
+
+ # If we previously inferred region-specific ratios, use them
+ if "region_inc_exp_ratio" in households.columns:
+ for region in households["region"].unique():
+ mask = households["region"] == region
+ region_ratio = households.loc[mask, "region_inc_exp_ratio"].iloc[0]
+ households.loc[mask, "inc"] = households.loc[mask, "exp"] * region_ratio
+
+ # If we manage to infer only country-wise ratio, use it
+ elif "country_inc_exp_ratio" in households.columns:
+ country_ratio = households["country_inc_exp_ratio"].iloc[0]
+ households["inc"] = households["exp"] * country_ratio
+
+ # If we don't have either, then use the ratio provided in config
+ elif params.get("inc_exp_ratio"):
+ inc_exp_ratio = params["inc_exp_ratio"]
+ households["inc"] = households["exp"] * inc_exp_ratio
+
+ else:
+ raise ValueError(
+ "No income-to-expenditure ratio found. Please provide region_inc_exp_ratio, country_inc_exp_ratio, or inc_exp_ratio in params."
+ )
+
+ return households
diff --git a/unbreakable/utils/data_generator.py b/unbreakable/utils/data_generator.py
new file mode 100644
index 0000000..05c0d67
--- /dev/null
+++ b/unbreakable/utils/data_generator.py
@@ -0,0 +1,260 @@
+import numpy as np
+import pandas as pd
+from typing import Dict, Literal
+
+# TODO: Generate example population impact data
+
+ROOF_SCORES: Dict[str, float] = {
+ "Concrete": 0.2,
+ "Finished – Concrete": 0.2,
+ "Finished – Metal": 0.4,
+ "Tile": 0.5,
+ "Shingle (asphalt)": 0.5,
+ "Shingle (other)": 0.5,
+ "Finished – Asbestos": 0.6,
+ "Shingle (wood)": 0.6,
+ "Sheet metal (galvanize, galvalume)": 0.65,
+ "Makeshift/thatched": 0.8,
+ "Natural – Thatch/palm leaf": 0.8,
+ "Other": 0.8,
+}
+
+WALL_SCORES: Dict[str, float] = {
+ "Concrete/Concrete blocks": 0.2,
+ "Concrete/Concrete Blocks": 0.2,
+ "Finished – Cement blocks": 0.3,
+ "Brick/Blocks": 0.35,
+ "Wood & Concrete": 0.4,
+ "Finished – Stone with lime/cement": 0.45,
+ "Finished – GRC/Gypsum/Asbestos": 0.5,
+ "Wood/Timber": 0.6,
+ "Natural – Other": 0.6,
+ "Plywood": 0.7,
+ "Rudimentary – Plywood": 0.7,
+ "Makeshift": 0.8,
+ "Other": 0.8,
+}
+
+FLOOR_SCORES: Dict[str, float] = {
+ "Finished – Cement/red bricks": 0.2,
+ "Finished – Parquet or polished wood": 0.4,
+ "Rudimentary – Wood planks": 0.5,
+ "Natural – Earth/sand": 0.7,
+ "Other": 0.6,
+}
+
+
+def generate_households(
+ num_households: int, num_spatial_units: int, seed: int = 0
+) -> pd.DataFrame:
+ """
+ Generate dummy households with various economic and demographic attributes based on income.
+
+ Args:
+ num_households (int): Number of households to generate.
+ num_spatial_units (int): Number of spatial units where households are located.
+ seed (int): Random seed for reproducibility.
+
+ Returns:
+ pd.DataFrame: DataFrame containing household data.
+ """
+ np.random.seed(seed)
+
+ # Constants
+ income_to_expenditure_ratio = 1.2
+ housing_expenditure_ratio = 0.3
+ effective_capital_stock_factor = 1 / 0.35
+ home_ownership_rate = 0.7
+ min_savings_rate = 0.05
+
+ # Generate base income data
+ income = np.random.normal(2000, 500, num_households)
+ income = np.clip(income, 1000, 3000)
+
+ # Generate additional columns based on income
+ female_headed = np.random.rand(num_households) < (
+ 0.3 - (income - 1000) / 2000 * 0.2
+ )
+ urban = np.random.rand(num_households) < ((income - 1000) / 2000 * 0.6 + 0.2)
+
+ # Determine literacy levels based on income
+ literacy_thresholds = np.percentile(income, [33, 66])
+ literacy = np.select(
+ [
+ income <= literacy_thresholds[0],
+ (income > literacy_thresholds[0]) & (income <= literacy_thresholds[1]),
+ income > literacy_thresholds[1],
+ ],
+ ["Low", "Medium", "High"],
+ default="Medium",
+ )
+
+ owns_home = np.random.rand(num_households) < (
+ (income - 1000) / 2000 * 0.5 + home_ownership_rate - 0.25
+ )
+
+ # Assign spatial units
+ spatial_units = [f"region_{i}" for i in range(num_spatial_units)]
+ assigned_spatial_units = np.random.choice(spatial_units, num_households)
+
+ data = {
+ "inc": income,
+ "owns_home": owns_home,
+ "keff": income * effective_capital_stock_factor,
+ "spatial_unit": assigned_spatial_units,
+ "female_headed": female_headed,
+ "urban": urban,
+ "literacy": literacy,
+ }
+
+ data["roof"] = [select_material(inc, ROOF_SCORES) for inc in income]
+ data["walls"] = [select_material(inc, WALL_SCORES) for inc in income]
+ data["floor"] = [select_material(inc, FLOOR_SCORES) for inc in income]
+
+ # Calculate housing expenditure
+ data["exp_house"] = np.where(
+ data["owns_home"], 0, income * housing_expenditure_ratio
+ )
+
+ # Calculate total expenditure ensuring minimum savings
+ max_expenditure = income * (1 - min_savings_rate)
+ data["exp"] = np.minimum(
+ income / income_to_expenditure_ratio, max_expenditure - data["exp_house"]
+ )
+
+ # Calculate savings
+ data["sav"] = income - data["exp"] - data["exp_house"]
+
+ # Assign each household a unique ID and weight
+ data["household_id"] = range(1, num_households + 1)
+ data["household_weight"] = np.random.uniform(1, 100, num_households)
+
+ # Define poverty line and poor status
+ poverty_line = np.percentile(data["inc"], 20)
+ data["poverty_line"] = poverty_line
+ data["is_poor"] = data["inc"] < poverty_line
+
+ # Sort columns
+ sorted_columns = [
+ "spatial_unit",
+ "household_id",
+ "household_weight",
+ "inc",
+ "exp",
+ "sav",
+ "owns_home",
+ "exp_house",
+ "keff",
+ "roof",
+ "walls",
+ "floor",
+ "poverty_line",
+ "is_poor",
+ "female_headed",
+ "urban",
+ "literacy",
+ ]
+
+ # Assert conditions
+ assert (
+ data["inc"] >= data["exp"] + data["exp_house"]
+ ).all(), "Income should be greater than expenditure"
+ assert (data["sav"] >= 0).all(), "Savings should be positive"
+ assert (data["exp"] >= 0).all(), "Expenditure should be positive"
+ assert (data["exp_house"] >= 0).all(), "Housing expenditure should be positive"
+
+ return pd.DataFrame(data)[sorted_columns]
+
+
+def select_material(income: float, material_scores: Dict[str, float]) -> str:
+ """
+ Select a material based on income, favoring lower vulnerability scores for higher incomes.
+
+ Args:
+ income (float): Household income
+ material_scores (Dict[str, float]): Dictionary of materials and their vulnerability scores
+
+ Returns:
+ str: Selected material
+ """
+ materials = list(material_scores.keys())
+ scores = np.array(list(material_scores.values()))
+
+ # Invert and normalize scores to use as probabilities
+ inv_scores = 1 - scores / scores.max()
+ probabilities = inv_scores / inv_scores.sum()
+
+ # Adjust probabilities based on income
+ income_factor = min(income / 3000, 1) # Normalize income, cap at 3000
+ adjusted_probs = probabilities * (1 + income_factor)
+ adjusted_probs /= adjusted_probs.sum()
+
+ return np.random.choice(materials, p=adjusted_probs)
+
+
+def generate_disaster_risk(disaster_type: str, num_spatial_units: int):
+ """Generate dummy disaster data for a given disaster type and number of spatial units."""
+ np.random.seed(42) # For reproducibility
+
+ spatial_units = [f"region_{i}" for i in range(num_spatial_units)]
+ return_periods = [10, 50, 100, 250] # Common return periods
+
+ data = []
+
+ for rp in return_periods:
+ rp_factor = rp / 250 # Normalize return period
+
+ for spatial_unit in spatial_units:
+ residential = np.random.uniform(100_000_000, 250_000_000)
+ non_residential = np.random.uniform(50_000_000, 100_000_000)
+ total = residential + non_residential
+
+ # Adjust PML and loss fraction based on disaster type and return period
+ if disaster_type == "flood":
+ base_loss = 0.05
+ max_loss = 0.3
+ elif disaster_type == "hurricane":
+ base_loss = 0.1
+ max_loss = 0.4
+ elif disaster_type == "earthquake":
+ base_loss = 0.15
+ max_loss = 0.5
+ else:
+ raise ValueError(f"Invalid disaster type: {disaster_type}")
+
+ # Calculate loss fraction ensuring it increases with return period
+ loss_fraction = base_loss + (max_loss - base_loss) * rp_factor
+ # Add some randomness
+ loss_fraction += np.random.uniform(-0.05, 0.05)
+ loss_fraction = max(
+ base_loss, min(max_loss, loss_fraction)
+ ) # Ensure within bounds
+
+ pml = total * loss_fraction
+
+ data.append(
+ {
+ "disaster_type": disaster_type,
+ "spatial_unit": spatial_unit,
+ "residential": round(residential, 2),
+ "non_residential": round(non_residential, 2),
+ "total_exposed_stock": round(total, 2),
+ "rp": rp,
+ "pml": round(pml, 2),
+ "loss_fraction": round(loss_fraction, 3),
+ }
+ )
+
+ return pd.DataFrame(data)
+
+
+if __name__ == "__main__":
+ # Generate dummy disaster risk and household survey data
+ disaster_types = ["flood", "hurricane", "earthquake"]
+ for disaster in disaster_types:
+ df = generate_disaster_risk(disaster, num_spatial_units=64)
+ df.to_csv(
+ f"../../data/processed/asset_impacts/Example/{disaster}.csv", index=False
+ )
+ households = generate_households(100, num_spatial_units=64)
+ households.to_csv("../../data/processed/household_survey/Example.csv", index=False)
diff --git a/unbreakable/utils/data_loader.py b/unbreakable/utils/data_loader.py
new file mode 100644
index 0000000..edce610
--- /dev/null
+++ b/unbreakable/utils/data_loader.py
@@ -0,0 +1,74 @@
+import pandas as pd
+from typing import List
+from typing import Dict, Optional, Any
+
+
+def load_data(params) -> tuple[pd.DataFrame, pd.DataFrame]:
+ """
+ Load households and disaster impact data for a given country and disaster specifications.
+
+ Args:
+ params (Dict[str, Any]): Parameters dictionary containing country, disaster_params, and recovery_params
+
+ Returns:
+ tuple[pd.DataFrame, pd.DataFrame]: DataFrames of household and disaster impact data.
+ """
+ country = params["country"]
+ impact_data_type = params["disaster_params"]["impact_data_type"]
+ disaster_spec = params["disaster_spec"]
+
+ households = pd.read_csv(f"../data/processed/household_survey/{country}.csv")
+
+ unique_disasters = set(disaster["type"] for disaster in disaster_spec)
+
+ impact_data = []
+ for disaster in unique_disasters:
+ if impact_data_type == "assets":
+ df = pd.read_csv(
+ f"../data/processed/asset_impacts/{country}/{disaster}.csv"
+ )
+ elif impact_data_type == "population":
+ df = pd.read_csv(
+ f"../data/processed/population_impacts/{country}/{disaster}.csv"
+ )
+ else:
+ raise ValueError(
+ f"Invalid impact_data_type: {impact_data_type}. Must be 'assets' or 'population'."
+ )
+ impact_data.append(df)
+
+ disaster_impacts = (
+ pd.concat(impact_data, ignore_index=True)
+ if len(impact_data) > 1
+ else impact_data[0]
+ )
+
+ return households, disaster_impacts
+
+
+def load_reconstruction_rates(params: Dict[str, Any]) -> Optional[pd.DataFrame]:
+ """
+ Load precomputed optimal reconstruction rates from a file.
+
+ Args:
+ params (Dict[str, Any]): Parameters dictionary containing recovery_params.
+
+ Returns:
+ Optional[pd.DataFrame]: Dataframe of reconstruction rates if file exists and should be used, None otherwise.
+ """
+
+ if not params["recovery_params"]["use_precomputed_reconstruction_rates"]:
+ return None
+
+ try:
+ return pd.read_csv(
+ f"../data/generated/{params['country']}/optimal_reconstruction_rates.csv"
+ )
+ except FileNotFoundError:
+ raise FileNotFoundError(
+ f"Reconstruction rates file not found for {params['country']}"
+ )
+ except Exception as e:
+ raise RuntimeError(
+ f"Error loading reconstruction rates for {params['country']}: {str(e)}"
+ )
diff --git a/unbreakable/utils/data_matcher.py b/unbreakable/utils/data_matcher.py
new file mode 100644
index 0000000..32633b1
--- /dev/null
+++ b/unbreakable/utils/data_matcher.py
@@ -0,0 +1,101 @@
+import pandas as pd
+import numpy as np
+
+
+def align_household_assets_with_exposure_data(
+ households: pd.DataFrame, exposure_data: pd.DataFrame, atol: float
+) -> pd.DataFrame:
+ """
+ Aligns household assets with exposure data and scales household economic indicators
+ for each spatial unit.
+
+ This function performs the following steps for each unique spatial unit:
+ 1. Matches household data with corresponding exposure data.
+ 2. Aligns the total household assets with the exposed assets from the exposure data.
+ 3. If there's a mismatch (within the specified tolerance), it scales the household
+ economic indicators to match the exposure data.
+
+ Args:
+ households (pd.DataFrame): Household survey data containing asset information
+ and other economic indicators.
+ exposure_data (pd.DataFrame): Exposure data containing information about total
+ exposed assets for each spatial unit.
+ atol (float): Absolute tolerance used for matching assets. If the difference
+ between household assets and exposed assets is within this tolerance,
+ no scaling is performed.
+
+ Returns:
+ pd.DataFrame: A DataFrame containing the aligned and potentially scaled
+ household data. If scaling was performed, original values are preserved
+ in columns with '_orig' suffix.
+
+ Note:
+ - The function assumes that both 'households' and 'exposure_data' DataFrames
+ have a 'spatial_unit' column for matching.
+ - The 'exposure_data' DataFrame should have a 'total_exposed_stock' column
+ representing the total exposed assets for each spatial unit.
+ - If scaling is performed, it affects the following columns in the household data:
+ 'exp', 'inc', 'sav', 'rent', 'k_house', and 'poverty_line'.
+ """
+ aligned_households = []
+ for spatial_unit in households["spatial_unit"].unique():
+ unit_households = households[households["spatial_unit"] == spatial_unit].copy()
+ exposed_assets = exposure_data.loc[
+ exposure_data["spatial_unit"] == spatial_unit, "total_exposed_stock"
+ ].iloc[0]
+ aligned_df = align_assets(unit_households, exposed_assets, atol)
+ aligned_households.append(aligned_df)
+ return pd.concat(aligned_households)
+
+
+def align_assets(
+ households: pd.DataFrame, exposed_assets: float, atol: float
+) -> pd.DataFrame:
+ """
+ Align household assets with exposed assets from disaster risk data.
+
+ Args:
+ households (pd.DataFrame): Household data for a specific spatial unit.
+ exposed_assets (float): Total exposed assets for the spatial unit.
+ atol (float): Absolute tolerance for asset matching.
+
+ Returns:
+ pd.DataFrame: Households with aligned assets and adjusted values.
+ """
+ survey_assets = (households["k_house"] * households["household_weight"]).sum()
+
+ if not np.isclose(exposed_assets, survey_assets, atol=atol):
+ scaling_factor = exposed_assets / survey_assets
+ households = scale_household_data(households, scaling_factor)
+
+ survey_assets_aligned = (
+ households["k_house"] * households["household_weight"]
+ ).sum()
+
+ assert round(exposed_assets) == round(
+ survey_assets_aligned
+ ), "Asset mismatch after alignment"
+
+ return households
+
+
+def scale_household_data(
+ households: pd.DataFrame, scaling_factor: float
+) -> pd.DataFrame:
+ """
+ Scale household data based on the calculated scaling factor.
+
+ Args:
+ households (pd.DataFrame): Household data to be scaled.
+ scaling_factor (float): Factor to scale the data by.
+
+ Returns:
+ pd.DataFrame: Scaled household data.
+ """
+ households["poverty_line_orig"] = households["poverty_line"].iloc[0]
+ households["k_house_orig"] = households["k_house"]
+
+ for column in ["exp", "inc", "sav", "rent", "k_house", "poverty_line"]:
+ households[column] *= scaling_factor
+
+ return households
diff --git a/unbreakable/utils/data_randomizer.py b/unbreakable/utils/data_randomizer.py
new file mode 100644
index 0000000..15bb60a
--- /dev/null
+++ b/unbreakable/utils/data_randomizer.py
@@ -0,0 +1,198 @@
+import pandas as pd
+import numpy as np
+from typing import Optional, Literal
+
+
+def randomize_rent(
+ households: pd.DataFrame, params: dict, random_seed: int
+) -> pd.DataFrame:
+ """
+ Randomize household rent based on estimated rent and provided parameters.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data with existing rent.
+ params (dict): Dictionary of parameters for randomization.
+
+ Returns:
+ pd.DataFrame: DataFrame with randomized rent.
+
+ Raises:
+ ValueError: If 'rent' column is not present in the DataFrame.
+ """
+ np.random.seed(random_seed)
+ if "rent" not in households.columns:
+ raise ValueError("'rent' column not found. Please estimate rent first.")
+
+ households = households.copy()
+ delta = params.get("delta", 0.05)
+ distribution = params.get("distribution", "uniform")
+
+ if distribution == "uniform":
+ multiplier = 1 + np.random.uniform(-delta, delta, len(households))
+ else:
+ raise ValueError(
+ f"Distribution '{distribution}' is not supported. Currently, only 'uniform' is available."
+ )
+
+ households["rent"] = households["rent"] * multiplier
+ return households
+
+
+def randomize_savings(
+ households: pd.DataFrame, params: dict, random_seed: int
+) -> pd.DataFrame:
+ """
+ Randomize household savings based on estimated savings and provided parameters.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data with existing savings.
+ params (dict): Dictionary of parameters for randomization.
+ random_seed (int): Random seed for reproducibility.
+
+ Returns:
+ pd.DataFrame: DataFrame with randomized savings.
+
+ Raises:
+ ValueError: If 'sav' or 'inc' columns are not present in the DataFrame.
+ """
+ if "sav" not in households.columns or "inc" not in households.columns:
+ raise ValueError(
+ "Both 'sav' and 'inc' columns must be present to randomize savings."
+ )
+ np.random.seed(random_seed)
+
+ households = households.copy()
+ saving_rate = households["sav"] / households["inc"]
+ delta = params.get("delta", 0.1)
+ distribution = params.get("distribution", "uniform")
+
+ if distribution == "uniform":
+ multiplier = 1 + np.random.uniform(-delta, delta, len(households))
+ else:
+ raise ValueError(
+ f"Distribution '{distribution}' is not supported. Currently, only 'uniform' is available."
+ )
+
+ households["sav"] = households["inc"] * saving_rate * multiplier
+
+ max_savings_rate = params.get("max_savings_rate", 0.2)
+ households["sav"] = np.minimum(
+ households["sav"], households["inc"] * max_savings_rate
+ )
+
+ return households
+
+
+def randomize_income(
+ households: pd.DataFrame, params: dict, random_seed: int
+) -> pd.DataFrame:
+ """
+ Randomize household incomes based on estimated incomes and provided parameters.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data with estimated incomes.
+ params (dict): Dictionary of parameters for randomization.
+ random_seed (int): Random seed for reproducibility.
+
+ Returns:
+ pd.DataFrame: DataFrame with randomized incomes.
+
+ Raises:
+ ValueError: If 'inc' column is not present in the DataFrame.
+ """
+ np.random.seed(random_seed)
+ if "inc" not in households.columns:
+ raise ValueError("'inc' column not found. Please estimate incomes first.")
+
+ households = households.copy()
+ randomized_ratio = randomize_ratio(
+ households["inc"] / households["exp"],
+ size=len(households),
+ distribution=params.get("distribution", "uniform"),
+ delta=params.get("delta", 0.1),
+ )
+ households["inc"] = households["exp"] * randomized_ratio
+ return households
+
+
+def randomize_ratio(
+ base_ratio: pd.Series, size: int, distribution: str = "uniform", delta: float = 0.1
+) -> np.ndarray:
+ """
+ Generate randomized income-to-expenditure ratios.
+
+ This function creates an array of randomized ratios based on a base ratio and specified distribution.
+
+ Args:
+ base_ratio (pd.Series): The base ratios to randomize.
+ size (int): Number of ratios to generate.
+ distribution (str): Type of distribution to use (default: 'uniform').
+ delta (float): Range of variation around the base_ratio (default: 0.1).
+
+ Returns:
+ np.ndarray: Array of randomized ratios.
+
+ Raises:
+ ValueError: If an unsupported distribution is specified.
+ """
+ if distribution == "uniform":
+ low = np.maximum(base_ratio - delta, 1.01) # Ensure ratio doesn't go below 1.01
+ high = base_ratio + delta
+ return np.random.uniform(low, high, size)
+ else:
+ raise ValueError(
+ f"Distribution '{distribution}' is not supported. Currently, only 'uniform' is available."
+ )
+
+
+def randomize_dwelling_vulnerability(
+ households: pd.DataFrame, params: dict, random_seed: int
+) -> pd.DataFrame:
+ """
+ Randomize dwelling vulnerability.
+
+ Args:
+ households (pd.DataFrame): Households DataFrame with 'v_init' column (initial vulnerability).
+ params (dict): Dict of parameters for randomization.
+ random_seed (int): Random seed for reproducibility.
+
+ Returns:
+ pd.DataFrame: Households with randomized vulnerability ('v' column added).
+
+ Raises:
+ ValueError: If the distribution is not supported or if required parameters are missing.
+ """
+ if not params.get("randomize", False):
+ if "v" not in households.columns:
+ households["v"] = households["v_init"]
+ return households
+
+ np.random.seed(random_seed)
+
+ distribution = params.get("distribution", "uniform")
+
+ if distribution != "uniform":
+ raise ValueError(
+ f"Distribution '{distribution}' is not supported. Only 'uniform' is currently supported."
+ )
+
+ # Extract parameters with default values
+ low = params.get("low", 0.9)
+ high = params.get("high", 1.1)
+ max_threshold = params.get("max_threshold", 0.9)
+ min_threshold = params.get("min_threshold", 0.2)
+
+ # Validate parameters
+ if not (0 < min_threshold < max_threshold < 1):
+ raise ValueError(
+ f"Invalid 'min_thresh' and 'max_thresh' values: {min_threshold}, {max_threshold}. Must be 0 < min_thresh < max_thresh < 1."
+ )
+
+ # Generate random values and calculate new vulnerability
+ random_factors = np.random.uniform(low, high, households.shape[0])
+ households["v"] = households["v_init"] * random_factors
+
+ # Apply thresholds using numpy for efficiency
+ households["v"] = np.clip(households["v"], min_threshold, max_threshold)
+
+ return households
diff --git a/unbreakable/utils/data_resampler.py b/unbreakable/utils/data_resampler.py
new file mode 100644
index 0000000..ceccebf
--- /dev/null
+++ b/unbreakable/utils/data_resampler.py
@@ -0,0 +1,74 @@
+import pandas as pd
+import numpy as np
+
+
+def resample_households_by_spatial_unit(
+ households: pd.DataFrame, min_households: int, random_seed: int = None
+) -> pd.DataFrame:
+ """Resample country households to be more representative.
+
+ Args:
+ households (pd.DataFrame): Households data.
+ min_households (int): Minimum number of households for representative sample.
+ random_seed (int, optional): Random seed for reproducibility. Defaults to None.
+
+ Returns:
+ pd.DataFrame: Resampled households.
+ """
+ households = households.copy()
+ households["household_id_orig"] = households["household_id"]
+ households["household_weight_orig"] = households["household_weight"]
+
+ resampled = (
+ households.groupby("spatial_unit")
+ .apply(
+ lambda x: upsample_spatial_unit_households(x, min_households, random_seed)
+ )
+ .reset_index(drop=True)
+ )
+
+ resampled["household_id"] = range(1, len(resampled) + 1)
+ return resampled
+
+
+def upsample_spatial_unit_households(
+ households: pd.DataFrame, min_households: int, random_seed: int = None
+) -> pd.DataFrame:
+ """Weighted resampling with adjustment for household representation within a spatial unit.
+
+ Args:
+ households (pd.DataFrame): Households of a specific spatial unit.
+ min_households (int): Minimum number of households for representative sample.
+ random_seed (int, optional): Random seed for reproducibility. Defaults to None.
+
+ Returns:
+ pd.DataFrame: Resampled households of a specific spatial unit.
+
+ Raises:
+ ValueError: If total weights after resampling is not equal to initial total weights.
+ """
+ np.random.seed(random_seed)
+ if len(households) >= min_households:
+ return households
+
+ initial_total_weights = households["household_weight"].sum()
+ delta = max(min_households - len(households), 2) # Ensure at least 2 samples
+
+ sample = households.sample(n=delta, replace=True, random_state=random_seed)
+ duplicated_households = pd.concat([households, sample], ignore_index=True)
+
+ duplication_counts = duplicated_households.groupby("household_id").size()
+ duplicated_households["household_weight"] /= duplication_counts[
+ duplicated_households["household_id"]
+ ].values
+
+ if not np.isclose(
+ duplicated_households["household_weight"].sum(),
+ initial_total_weights,
+ atol=1e-6,
+ ):
+ raise ValueError(
+ "Total weights after duplication is not equal to the initial total weights"
+ )
+
+ return duplicated_households
diff --git a/unbreakable/utils/data_validator.py b/unbreakable/utils/data_validator.py
new file mode 100644
index 0000000..4587a03
--- /dev/null
+++ b/unbreakable/utils/data_validator.py
@@ -0,0 +1,97 @@
+import pandas as pd
+import numpy as np
+from typing import Optional
+
+
+def validate_rent(
+ rent: pd.Series, income: pd.Series, expenditure: pd.Series
+) -> Optional[ValueError]:
+ """
+ Validate the generated rent.
+
+ This function checks if the generated rent values are valid:
+ - Not NaN
+ - Positive
+ - Less than income
+ - Less than expenditure
+
+ Args:
+ rent (pd.Series): Series of generated rent values.
+ income (pd.Series): Series of income values.
+ expenditure (pd.Series): Series of expenditure values.
+
+ Returns:
+ None if validation passes.
+
+ Raises:
+ ValueError: If any validation check fails.
+ """
+ if rent.isna().any():
+ raise ValueError("Rent cannot be NaN")
+ if (rent <= 0).any():
+ raise ValueError("Rent must be positive")
+ if (rent >= income).any():
+ raise ValueError("Rent must be less than income")
+ if (rent >= expenditure).any():
+ raise ValueError("Rent must be less than expenditure")
+ return None
+
+
+def validate_income(income: pd.Series, expenditure: pd.Series) -> Optional[ValueError]:
+ """
+ Validate the generated income.
+
+ This function checks if the generated income values are valid:
+ - Not NaN
+ - Positive
+ - Greater than corresponding expenditure
+
+ Args:
+ income (pd.Series): Series of generated income values.
+ expenditure (pd.Series): Series of corresponding expenditure values.
+
+ Returns:
+ None if validation passes.
+
+ Raises:
+ ValueError: If any validation check fails.
+ """
+ if income.isna().any():
+ raise ValueError("Income cannot be NaN")
+ if (income <= 0).any():
+ raise ValueError("Income must be positive")
+ if (income <= expenditure).any():
+ raise ValueError("Income must be greater than expenditure")
+ return None
+
+
+def validate_savings(
+ savings: pd.Series, income: pd.Series, expenditure: pd.Series
+) -> Optional[ValueError]:
+ """
+ Validate the generated savings.
+
+ This function checks if the generated savings values are valid:
+ - Not NaN
+ - Not negative
+ - Not greater than income
+ - Consistent with income - expenditure
+
+ Args:
+ savings (pd.Series): Series of generated savings values.
+ income (pd.Series): Series of income values.
+ expenditure (pd.Series): Series of expenditure values.
+
+ Returns:
+ None if validation passes.
+
+ Raises:
+ ValueError: If any validation check fails.
+ """
+ if savings.isna().any():
+ raise ValueError("Savings cannot be NaN")
+ if (savings < 0).any():
+ raise ValueError("Savings cannot be negative")
+ if (savings > income).any():
+ raise ValueError("Savings cannot be greater than income")
+ return None
diff --git a/unbreakable/utils/household_data_preprocessor.py b/unbreakable/utils/household_data_preprocessor.py
new file mode 100644
index 0000000..cb9451b
--- /dev/null
+++ b/unbreakable/utils/household_data_preprocessor.py
@@ -0,0 +1,177 @@
+import pandas as pd
+import numpy as np
+from typing import Optional
+from unbreakable.utils.data_validator import *
+from unbreakable.utils.data_estimator import *
+from unbreakable.utils.data_randomizer import *
+from unbreakable.utils.data_resampler import *
+from unbreakable.utils.data_matcher import *
+
+
+def prepare_household_data(
+ households: pd.DataFrame,
+ disaster_impacts: pd.DataFrame,
+ params: dict,
+ random_seed: int,
+) -> pd.DataFrame:
+ """
+ Prepare household data by updating, estimating and/or randomizing them based on provided parameters.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data.
+ disaster_impacts (pd.DataFrame): DataFrame containing disaster impacts data.
+ params (dict): Dictionary of parameters for randomization.
+ random_seed (int): Random seed for reproducibility.
+
+ Returns:
+ pd.DataFrame: DataFrame with updated household data.
+ """
+ np.random.seed(random_seed)
+ households = get_income(households, params["income_params"], random_seed)
+ households = get_savings(households, params["savings_params"], random_seed)
+ households = get_rent(households, params["rent_params"], random_seed)
+
+ # Resample households to ensure minimum number of households for representative sample
+ households = resample_households_by_spatial_unit(
+ households, params["min_households"], random_seed
+ )
+
+ # * This must be done after resampling and before matching
+ households = estimate_effective_capital_stock(households, params)
+
+ if params["disaster_params"]["impact_data_type"] == "assets":
+ # There could be a mismatch between the assets in the household data and the exposure data
+ households = align_household_assets_with_exposure_data(
+ households, disaster_impacts, params["atol"]
+ )
+
+ # Estimate welfare based on consumption utility
+ households = estimate_welfare(households, params)
+
+ return households
+
+
+def get_rent(households: pd.DataFrame, params: dict, random_seed: int) -> pd.DataFrame:
+ """
+ Estimate and/or randomize household rent based on provided parameters.
+
+ This function serves as a wrapper to call the estimate_rent and randomize_rent
+ functions based on the provided parameters.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data.
+ params (dict): Dictionary of parameters for estimation and randomization.
+ random_seed (int): Random seed for reproducibility.
+
+ Returns:
+ pd.DataFrame: DataFrame with estimated and/or randomized rent.
+
+ Raises:
+ ValueError: If invalid combination of estimate and randomize parameters are provided.
+ """
+ estimate = params.get("estimate", False)
+ randomize = params.get("randomize", False)
+
+ if estimate and not randomize:
+ households = estimate_rent(households, params)
+ elif randomize and not estimate:
+ if "rent" not in households.columns:
+ raise ValueError(
+ "'rent' column not found. Cannot randomize without existing rent estimates."
+ )
+ households = randomize_rent(households, params, random_seed)
+ elif estimate and randomize:
+ households = estimate_rent(households, params)
+ households = randomize_rent(households, params, random_seed)
+ else:
+ # If neither estimate nor randomize is True, return the original households
+ return households
+
+ validate_rent(households["rent"], households["inc"], households["exp"])
+ return households
+
+
+def get_savings(
+ households: pd.DataFrame, params: dict, random_seed: int
+) -> pd.DataFrame:
+ """
+ Estimate and/or randomize household savings based on provided parameters.
+
+ This function serves as a wrapper to call the estimate_savings and randomize_savings
+ functions based on the provided parameters.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data.
+ params (dict): Dictionary of parameters for estimation and randomization.
+ random_seed (int): Random seed for reproducibility.
+
+ Returns:
+ pd.DataFrame: DataFrame with estimated and/or randomized savings.
+
+ Raises:
+ ValueError: If invalid combination of estimate and randomize parameters are provided.
+ """
+ estimate = params.get("estimate", False)
+ randomize = params.get("randomize", False)
+
+ if estimate and not randomize:
+ households = estimate_savings(households, params)
+ elif randomize and not estimate:
+ if "sav" not in households.columns:
+ raise ValueError(
+ "'sav' column not found. Cannot randomize without existing savings estimates."
+ )
+ households = randomize_savings(households, params, random_seed)
+ elif estimate and randomize:
+ households = estimate_savings(households, params)
+ households = randomize_savings(households, params, random_seed)
+ else:
+ # If neither estimate nor randomize is True, return the original households
+ return households
+
+ validate_savings(households["sav"], households["inc"], households["exp"])
+ return households
+
+
+def get_income(
+ households: pd.DataFrame, params: dict, random_seed: int
+) -> pd.DataFrame:
+ """
+ Estimate and/or randomize household incomes based on provided parameters.
+
+ This function serves as a wrapper to call the estimate_income and randomize_income
+ functions based on the provided parameters.
+
+ Args:
+ households (pd.DataFrame): DataFrame containing household data.
+ params (dict): Dictionary of parameters for estimation and randomization.
+ random_seed (int): Random seed for reproducibility.
+
+ Returns:
+ pd.DataFrame: DataFrame with estimated and/or randomized incomes.
+
+ Raises:
+ ValueError: If neither estimate nor randomize parameters are provided.
+ """
+ estimate = params.get("estimate", False)
+ randomize = params.get("randomize", False)
+
+ if estimate and not randomize:
+ households = estimate_income(households, params)
+
+ elif randomize and not estimate:
+ if "inc" not in households.columns:
+ raise ValueError(
+ "'inc' column not found. Cannot randomize without existing income estimates."
+ )
+ households = randomize_income(households, params, random_seed)
+
+ elif estimate and randomize:
+ households = estimate_income(households, params)
+ households = randomize_income(households, params, random_seed)
+ else:
+ # If neither estimate nor randomize is True, return the original households
+ return households
+
+ validate_income(households["inc"], households["exp"])
+ return households