Skip to content

Commit 392eac4

Browse files
committedApr 3, 2025·
economic module integration
1 parent 566fbb1 commit 392eac4

9 files changed

+166
-99
lines changed
 

‎inputs/en/demo_national_input.xlsx

71 Bytes
Binary file not shown.

‎nutrition/data.py

Lines changed: 29 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -349,63 +349,55 @@ def get_time_trends(self):
349349

350350
@translate
351351
def get_economic_cost(self):
352-
econo_inputs = utils.read_sheet(self._spreadsheet, _("Economic inputs"), cols=[0], dropna=False)
353-
life_exp = econo_inputs.loc[_("Life expectancy at birth")].values[0]
354-
gdp_growth = econo_inputs.loc[_("GDP growth rate")].values[0]
355-
gdp_pc = econo_inputs.loc[_("Life expectancy at birth")].values[0]
356-
per_earn_realised = econo_inputs.loc[_("Percentage of lifetime earning actually realized")].values[0]
357-
age_end_prod = econo_inputs.loc[_("Age for end of productivity")].values[0]
358-
age_sta_prod = econo_inputs.loc[_("Age start productivity")].values[0]
359-
fem_lb_part = econo_inputs.loc[_("Female labor force participation")].values[0]
360-
prop_pw_benef = econo_inputs.loc[_("Proportion of pregnancy to apply benefits to")].values[0]
361-
inc_iq_bf = econo_inputs.loc[_("Increase in IQ due to early breastfeeding")].values[0]
362-
inc_ear_iq = econo_inputs.loc[_("Increase in earnings due to increase in one IQ pt")].values[0]
363-
lab_share_gdp = econo_inputs.loc[_("Labor share of GDP")].values[0]
364-
low_earn_stunted = econo_inputs.loc[_("Percentage of lower lifetime earning of a stunted individual")].values[0]
365-
produc_gain_anemia = econo_inputs.loc[_("Gains in productivity from averted childhood anemia")].values[0]
366-
produc_gain_lbw = econo_inputs.loc[_("Productivity gains due to averted low birth weight")].values[0]
367-
wage_share_manual = econo_inputs.loc[_("Wage Share in GDP for manual occupations")].values[0]
368-
produc_light_lab = econo_inputs.loc[_("Gains productivity in light labour")].values[0]
369-
blue_col_share = econo_inputs.loc[_("Blue-Collar Share employment in total employment")].values[0]
370-
heavy_manu_lab = econo_inputs.loc[_("Wage Share of Heavy manual labor")].values[0]
371-
produc_heavy_lab = econo_inputs.loc[_("Gains in productivity in heavy labor")].values[0][0]
352+
econo_inputs = utils.read_sheet(self._spreadsheet, _("Economic inputs"), cols=[0], dropna=False)
353+
gdp_growth = econo_inputs.loc[_("GDP growth rate")].values[0]
354+
gdp_pc = econo_inputs.loc[_("GDP per capita")].values[0]
355+
discount_rate = econo_inputs.loc[_("Rate of dicounting")].values[0]
356+
per_earn_realised = econo_inputs.loc[_("Percentage of lifetime earning actually realized")].values[0]
357+
age_end_prod = econo_inputs.loc[_("Age for end of productivity")].values[0]
358+
age_sta_prod = econo_inputs.loc[_("Age start productivity")].values[0]
359+
fem_lb_part = econo_inputs.loc[_("Female labor force participation")].values[0]
360+
prop_pw_benef = econo_inputs.loc[_("Proportion of pregnancy to apply benefits to (maternal anemia)")].values[0]
361+
inc_iq_bf = econo_inputs.loc[_("Increase in IQ points due to early breastfeeding")].values[0]
362+
inc_ear_iq = econo_inputs.loc[_("Increase in earnings due to increase in one IQ pt")].values[0]
363+
lab_share_gdp = econo_inputs.loc[_("Labor share of GDP")].values[0][0]
364+
low_earn_stunted = econo_inputs.loc[_("Percentage of lower lifetime earning of a stunted individual")].values[0]
365+
produc_loss_anemia = econo_inputs.loc[_("Loss in productivity from due to childhood anemia")].values[0]
366+
produc_loss_lbw = econo_inputs.loc[_("Loss in productivity due to low birth weight")].values[0]
367+
produc_loss_mat_ane = econo_inputs.loc[_("Loss in productivity due to maternal anemia")].values[0]
368+
369+
econo_inputs = utils.read_sheet(self._spreadsheet, _("Economic inputs"), cols=[0], skiprows=18)
372370

373-
econo_inputs = utils.read_sheet(self._spreadsheet, _("Economic inputs"), cols=[0], skiprows=22)
371+
num_people = econo_inputs.loc[_("Number of people left alive (starting with 100,000 births)")].values.tolist()
374372

375-
num_people = econo_inputs.loc[_("Number of people")].values.tolist()
376-
377-
self.econ_inputs = {"Life expectancy at birth": life_exp,
378-
"GDP growth rate": gdp_growth,
379-
"GDP per capita": gdp_pc ,
373+
self.econ_inputs = {"GDP growth rate": gdp_growth,
374+
"GDP per capita": gdp_pc,
375+
"Discount rate": discount_rate,
380376
"Percent of lifetime earning actually realized": per_earn_realised,
381377
"Productivity year end": age_end_prod,
382378
"Productivity year start": age_sta_prod,
383379
"Female labor force participation": fem_lb_part,
384-
"Proportion of pregnancy to apply benefits to": prop_pw_benef,
380+
"Proportion of pregnancy to apply benefits to (maternal anemia)": prop_pw_benef,
385381
"Percentage of pregnant women 15-19 years": self.pw_agedist[0],
386382
"Percentage of pregnant women 20-29 years": self.pw_agedist[1],
387383
"Percentage of pregnant women 30-39 years": self.pw_agedist[2],
388384
"Percentage of pregnant women 40-49 years": self.pw_agedist[3],
389-
"Increase in IQ due to EBF": inc_iq_bf,
385+
"Increase in IQ points due to early breastfeeding": inc_iq_bf,
390386
"Rate of increase in earnings from IQ": inc_ear_iq,
391387
"Labor share of GDP": lab_share_gdp,
392388
"Percent lower lifetime earning of a stunted": low_earn_stunted,
393-
"Productivity gain from averting child anemia": produc_gain_anemia,
394-
"Productivity gain from averting LBW": produc_gain_lbw,
395-
"Wage Share in GDP for manual occupations": wage_share_manual,
396-
"Gains productivity in light labour": produc_light_lab,
397-
"Blue-Collar Share employment in total employment": blue_col_share,
398-
"Wage Share of Heavy manual labor": heavy_manu_lab,
399-
"Gains in productivity in heavy labor": produc_heavy_lab,
400-
"Number of people per 100,000": num_people}
389+
"Productivity loss due to child anemia": produc_loss_anemia,
390+
"Productivity loss due to LBW": produc_loss_lbw,
391+
"Loss in productivity due to maternal anemia": produc_loss_mat_ane,
392+
"Number of people left alive (starting with 100,000 births)": num_people}
401393

402394
def get_lifetable(self):
403395
all_ages = [a for a in range(5,66)]
404396
age_cats = ["5-9 years", "10-14 years", "15-19 years", "20-24 years", "25-29 years",
405397
"30-34 years", "35-39 years", "40-44 years", "45-49 years", "50-54 years",
406398
"55-59 years", "60-64 years","65-69 years"]
407399

408-
number_list = self.econ_inputs["Number of people per 100,000"]
400+
number_list = self.econ_inputs["Number of people left alive (starting with 100,000 births)"]
409401
people_number = {age_cat: 0 for age_cat in age_cats}
410402
for c, cat in enumerate(age_cats):
411403
people_number[cat] = number_list[c]

‎nutrition/model.py

Lines changed: 89 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,9 @@ def __init__(self, dataset: Dataset, t=None, adjust_cov=False, timeTrends=False,
3030
self.enforce_constraints_year = enforce_constraints_year
3131

3232
# For economic loss
33-
self.cost_wasting = self.demo_data.cost_wasting
34-
self.cost_stunting = self.demo_data.cost_stunting
35-
self.cost_child_death = self.demo_data.cost_child_death
36-
self.cost_pw_death = self.demo_data.cost_pw_death
37-
self.cost_child_anaemic = self.demo_data.cost_child_anaemic
38-
self.cost_pw_anaemic = self.demo_data.cost_pw_anaemic
39-
33+
self.econ_inputs = self.demo_data.econ_inputs # this comes as a dictionary of several economic inputs reqired for economic cost/benefit calculations
34+
self.life_table = self.demo_data.life_table
35+
4036
@property
4137
def locale(self):
4238
return self.ss.locale
@@ -145,18 +141,93 @@ def _track_rates(self):
145141
self.child_mortrate[self.year] = 1000 * np.sum(self.child_deaths) / np.sum(self.annual_births)
146142
self.pw_mortrate[self.year] = 1000 * np.sum(self.pw_deaths) / np.sum(self.annual_births)
147143

144+
# def _track_economic_loss(self):
145+
# """To calculate the economic cost of children become stunting or wasting for the country.
146+
# Simply, the cost of stunting and cost of wasting have been input over the databook."""
147+
# oldest = self.children.age_groups[-1]
148+
# rate = oldest.ageingRate
149+
# self.stunting_cost[self.year] += oldest.num_stunted() * rate * self.cost_wasting
150+
# self.wasting_cost[self.year] += sum(oldest.num_wasted(cat) for cat in self.ss.wasted_list) * rate * self.cost_stunting
151+
# self.child_death_cost[self.year] = np.sum(self.child_deaths) * self.cost_child_death
152+
# self.pw_death_cost[self.year] = np.sum(self.pw_deaths) * self.cost_pw_death
153+
# self.child_anaemic_cost[self.year] = oldest.num_anaemic() * rate * self.cost_child_anaemic
154+
# self.pw_anaemic_cost[self.year] = self.pw.num_anaemic() * self.cost_pw_anaemic
155+
148156
def _track_economic_loss(self):
149-
"""To calculate the economic cost of children become stunting or wasting for the country.
150-
Simply, the cost of stunting and cost of wasting have been input over the databook."""
151-
oldest = self.children.age_groups[-1]
152-
rate = oldest.ageingRate
153-
self.stunting_cost[self.year] += oldest.num_stunted() * rate * self.cost_wasting
154-
self.wasting_cost[self.year] += sum(oldest.num_wasted(cat) for cat in self.ss.wasted_list) * rate * self.cost_stunting
155-
self.child_death_cost[self.year] = np.sum(self.child_deaths) * self.cost_child_death
156-
self.pw_death_cost[self.year] = np.sum(self.pw_deaths) * self.cost_pw_death
157-
self.child_anaemic_cost[self.year] = oldest.num_anaemic() * rate * self.cost_child_anaemic
158-
self.pw_anaemic_cost[self.year] = self.pw.num_anaemic() * self.cost_pw_anaemic
159-
157+
bene_age_start = self.econ_inputs[_("Productivity year start")]
158+
bene_age_end = self.econ_inputs[_("Productivity year end")]
159+
start_year = self.demo_data.t[0]
160+
161+
self.child_death_cost[self.year] = 0
162+
self.stunting_cases_cost[self.year] = 0
163+
self.mat_death_cost[self.year] = 0
164+
self.ch_anemia_cost[self.year] = 0
165+
self.bf_benefit[self.year] = 0
166+
self.lbw_cost[self.year] = 0
167+
168+
for a, age in enumerate(range(bene_age_start, bene_age_end + 1)):
169+
probability_5yr = self.life_table[(self.life_table[_("Age")] == age)][_("Proportion left since age 5")].item()
170+
171+
172+
"""Stunting cases"""
173+
174+
this_stun_cases_cost = self.stunted[self.year] * probability_5yr * self.econ_inputs[_("Percent of lifetime earning actually realized")]\
175+
* self.econ_inputs[_("Percent lower lifetime earning of a stunted")] * self.econ_inputs[_("GDP per capita")] * ((1 + self.econ_inputs[_("GDP growth rate")]) ** (self.year + age - 1))\
176+
* ((1 + self.econ_inputs[_("Discount rate")]) ** -(self.year + age - 1))
177+
178+
"""Child Anemia cases"""
179+
child_anemia = self.child_anaemprev[self.year] * self.child_less_5years[self.year] / 5
180+
this_ch_anem_cases_cost = child_anemia * probability_5yr * self.econ_inputs[_("Percent of lifetime earning actually realized")]\
181+
* self.econ_inputs[_("Productivity loss due to child anemia")] * self.econ_inputs[_("Labor share of GDP")]\
182+
* self.econ_inputs[_("GDP per capita")] * ((1 + self.econ_inputs[_("GDP growth rate")]) ** (self.year + age - 1))\
183+
* ((1 + self.econ_inputs[_("Discount rate")]) ** -(self.year + age - 1))
184+
185+
""" Child deaths"""
186+
this_ch_death_cost = self.child_deaths[self.year] * probability_5yr * self.econ_inputs[_("Percent of lifetime earning actually realized")]\
187+
* self.econ_inputs[_("GDP per capita")] * ((1 + self.econ_inputs[_("GDP growth rate")]) ** (self.year + age - 1))\
188+
* ((1 + self.econ_inputs[_("Discount rate")]) ** -(self.year + age - 1))
189+
190+
"""Additional EBF"""
191+
num_bf = self.child_1_6months[self.year] * self.child_bfprev[self.year] * 2
192+
this_bf_cognitive_benefit = num_bf * probability_5yr * self.econ_inputs[_("Percent of lifetime earning actually realized")]\
193+
* self.econ_inputs[_("Increase in IQ points due to early breastfeeding")] * self.econ_inputs[_("Rate of increase in earnings from IQ")] * self.econ_inputs[_("Labor share of GDP")]\
194+
* self.econ_inputs[_("GDP per capita")] * ((1 + self.econ_inputs[_("GDP growth rate")]) ** (self.year + age))\
195+
* ((1 + self.econ_inputs[_("Discount rate")]) ** -(self.year + age - 1))
196+
197+
"""Low Birth Weight children averted"""
198+
this_lbw_cost = self.child_sga[self.year] * probability_5yr * self.econ_inputs[_("Percent of lifetime earning actually realized")]\
199+
* self.econ_inputs[_("Labor share of GDP")] * self.econ_inputs[_("Productivity loss due to LBW")] * self.econ_inputs[_("GDP per capita")]\
200+
* ((1 + self.econ_inputs[_("GDP growth rate")]) ** (self.year + age)) * ((1 + self.econ_inputs[_("Discount rate")]) ** -(self.year + age - 1))
201+
202+
"""Maternal deaths averted"""
203+
probability_15yr = self.life_table[(self.life_table["Age"] == age)][_("Proportion left since age 15")].item()
204+
probability_25yr = self.life_table[(self.life_table["Age"] == age)][_("Proportion left since age 25")].item()
205+
probability_35yr = self.life_table[(self.life_table["Age"] == age)][_("Proportion left since age 35")].item()
206+
probability_45yr = self.life_table[(self.life_table["Age"] == age)][_("Proportion left since age 45")].item()
207+
208+
209+
this_maternal_death_cost = self.pw_deaths[self.year] * (probability_15yr * self.econ_inputs[_("Percentage of pregnant women 15-19 years")] + probability_25yr * self.econ_inputs[_("Percentage of pregnant women 20-29 years")]\
210+
+ probability_35yr * self.econ_inputs[_("Percentage of pregnant women 30-39 years")] + probability_45yr * self.econ_inputs[_("Percentage of pregnant women 40-49 years")]) * self.econ_inputs[_("Percent of lifetime earning actually realized")]\
211+
* self.econ_inputs[_("Female labor force participation")] * self.econ_inputs[_("GDP per capita")] * ((1 + self.econ_inputs[_("GDP growth rate")]) ** (self.year + a - 1))\
212+
* ((1 + self.econ_inputs[_("Discount rate")]) ** -(self.year + a - 1))
213+
214+
215+
""""Totalling the future lifetime benefits for the averted/additional cases for this year [t]"""
216+
217+
self.child_death_cost[self.year] = self.child_death_cost[self.year] + this_ch_death_cost
218+
self.stunting_cases_cost[self.year] = self.stunting_cases_cost[self.year] + this_stun_cases_cost
219+
self.ch_anemia_cost[self.year] = self.ch_anemia_cost[self.year] + this_ch_anem_cases_cost
220+
self.bf_benefit[self.year] = self.bf_benefit[self.year] + this_bf_cognitive_benefit
221+
self.lbw_cost[self.year] = self.lbw_cost[self.year] + this_lbw_cost
222+
self.mat_death_cost[self.year] = self.mat_death_cost[self.year] + this_maternal_death_cost
223+
224+
pw_ane = self.pw_anaemic[self.year] / 0.75
225+
self.mat_anemia_cases_cost[self.year] = pw_ane * (self.econ_inputs[_("Loss in productivity due to maternal anemia")] * self.econ_inputs[_("Proportion of pregnancy to apply benefits to (maternal anemia)")] * self.econ_inputs[_("Female labor force participation")]\
226+
* self.econ_inputs[_("GDP per capita")]) * ((1 + self.econ_inputs[_("GDP growth rate")]) ** (self.year - 1)) * ((1 + self.econ_inputs[_("Discount rate")]) ** -(self.year - 1))
227+
228+
self.total_econ_costs[self.year] = self.child_death_cost[self.year] + self.stunting_cases_cost[self.year] + self.ch_anemia_cost[self.year] + self.lbw_cost[self.year] + self.mat_death_cost[self.year] + self.mat_anemia_cases_cost[self.year]
229+
230+
160231
def _track_total_pop(self):
161232
self.pop_sizes[self.year] = dict()
162233
for pop in self.pops:

‎nutrition/utils.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,14 @@ def default_trackers(prev=None, rate=None):
127127
"child_6_23months",
128128
"child_less_5years",
129129
"num_pw",
130-
"stunting_cost",
131-
"wasting_cost",
132130
"child_death_cost",
133-
"pw_death_cost",
134-
"child_anaemic_cost",
135-
"pw_anaemic_cost",
131+
"stunting_cases_cost",
132+
"ch_anemia_cost",
133+
"bf_benefit",
134+
"lbw_cost",
135+
"mat_death_cost",
136+
"mat_anemia_cases_cost",
137+
"total_econ_costs",
136138
"pw_mortrate",
137139
"total_popn",
138140
"pop_rate",
@@ -212,12 +214,14 @@ def pretty_labels(direction=False, locale=None):
212214
pgettext("plotting", "Number of children 6-23 months"),
213215
pgettext("plotting", "Number of children <5 years"),
214216
pgettext("plotting", "Number of pregnant women"),
215-
pgettext("plotting", "Economic cost of stunting"),
216-
pgettext("plotting", "Economic cost of wasting"),
217-
pgettext("plotting", "Economic cost of child death"),
218-
pgettext("plotting", "Economic cost of pregnant woman death"),
219-
pgettext("plotting", "Economic cost of ID anaemic child"),
220-
pgettext("plotting", "Economic cost of ID anaemic pregnant woman"),
217+
pgettext("plotting", "Economic cost of child deaths (discounted)"),
218+
pgettext("plotting", "Economic cost of stunting (discounted)"),
219+
pgettext("plotting", "Economic cost of child anemia (discounted)"),
220+
pgettext("plotting", "Economic benefits of EBF (discounted)"),
221+
pgettext("plotting", "Economic cost of low birth weight chidren (discounted)"),
222+
pgettext("plotting", "Economic cost of maternal deaths (discounted)"),
223+
pgettext("plotting", "Economic cost of maternal anemia (discounted)"),
224+
pgettext("plotting", "Total economic cost (discounted)"),
221225
pgettext("plotting", "Pregnant women mortality rate"),
222226
pgettext("plotting", "Total population"),
223227
pgettext("plotting", "Population growth rate"),
@@ -255,7 +259,7 @@ def relabel(old, direction=False, lower=False, locale=None):
255259

256260

257261
def get_sign(obj):
258-
max_obj = ["thrive", "child_notanaemic", "child_healthy", "child_notwasted"]
262+
max_obj = ["thrive", "child_notanaemic", "child_healthy", "child_notwasted", "bf_benefit"]
259263
if obj in max_obj:
260264
return -1
261265
else:

‎tests/optim_results.xlsx

35.2 KB
Binary file not shown.

‎tests/scen_results_test_2025.xlsx

71.2 KB
Binary file not shown.

‎tests/test.prj

62.6 KB
Binary file not shown.

0 commit comments

Comments
 (0)
Please sign in to comment.