11
11
import pandas as pd
12
12
from matplotlib import pyplot as plt
13
13
14
+ from tlo import Date
14
15
from tlo .analysis .utils import (
16
+ CAUSE_OF_DEATH_OR_DALY_LABEL_TO_COLOR_MAP ,
15
17
extract_results ,
16
18
format_gbd ,
17
19
get_color_cause_of_death_or_daly_label ,
@@ -166,7 +168,7 @@ def _sort_columns(df):
166
168
167
169
fig , ax = plt .subplots ()
168
170
plot_clustered_stacked (ax = ax ,
169
- dfall = _dat ,
171
+ dfall = ({ k : v / 1e3 for k , v in _dat . items ()} if what == 'DALYs' else _dat ) ,
170
172
color_for_column_map = get_color_cause_of_death_or_daly_label ,
171
173
scaled = scaled ,
172
174
legends = False ,
@@ -178,7 +180,6 @@ def _sort_columns(df):
178
180
ax .set_xlabel ('Age Group' )
179
181
ax .set_xticklabels (ax .get_xticklabels (), rotation = 90 )
180
182
181
- # ax.set_xlim([0, 17.5])
182
183
if scaled :
183
184
ax .set_ylim ([0 , 1.05 ])
184
185
else :
@@ -188,23 +189,22 @@ def _sort_columns(df):
188
189
ax .set_ylim ([0 , 25_000 ])
189
190
ax .set_yticks (np .arange (0 , 30_000 , 5_000 ))
190
191
else :
191
- ax .set_ylabel (f"{ what } per year\n " )
192
+ ax .set_ylabel (f"{ what } per year (/1000)\n " )
193
+ ax .set_ylim ([0 , 2000.0 ])
192
194
193
195
# Create figure legend and remove duplicated entries, but keep the first entries
194
196
handles , labels = ax .get_legend_handles_labels ()
195
197
lgd = dict ()
196
198
for k , v in zip (labels , handles ):
197
199
lgd .setdefault (k , v )
198
- ax .legend (reversed (lgd .values ()), reversed (lgd .keys ()), loc = "upper right" , ncol = 2 , fontsize = 8 )
200
+ # ax.legend(reversed(lgd.values()), reversed(lgd.keys()), loc="upper right", ncol=2, fontsize=8)
201
+ # ax.text(
202
+ # 5.2, 11_000, 'GBD || Model', horizontalalignment='left', verticalalignment='bottom', fontsize=8)
203
+ ax .legend ().set_visible (False ) # Hide legend
199
204
200
205
fig .tight_layout ()
201
206
fig .savefig (make_graph_file_name (
202
207
f"{ what } _{ period } _{ sex } _StackedBars_ModelvsGBD_{ 'scaled' if scaled else '' } " ))
203
-
204
- # ax.text(
205
- # 5.2, 11_000, 'GBD || Model', horizontalalignment='left', verticalalignment='bottom', fontsize=8)
206
- ax .legend ().set_visible (False )
207
-
208
208
plt .close (fig )
209
209
210
210
# Simple pie-charts of just TLO estimates
@@ -296,9 +296,9 @@ def shift_row_to_top(df, index_to_shift):
296
296
dat : outcome_by_age_pt [dat ].sum (axis = 0 ) for dat in outcome_by_age_pt .keys ()
297
297
}, axis = 1
298
298
)
299
- # todo N.B. For GBD, should really use all ages and all sex numbers from GBD to get correct uncertainty bounds
300
- # (the addition of the bounds for the sub-categories - as done here - is not strictly correct.)
301
- # ... OR use formula to make my own explicit assumption about correlation of uncertainty in different age-grps .
299
+ # todo N.B. For GBD, would ideally use all ages and all sex numbers from GBD to get correct uncertainty bounds
300
+ # (the addition of the bounds for the sub-categories - as done here - might over-state the uncertainty.) This
301
+ # plot should be taken as indicative only .
302
302
303
303
select_labels = []
304
304
@@ -311,6 +311,11 @@ def shift_row_to_top(df, index_to_shift):
311
311
312
312
for cause in all_causes :
313
313
314
+ if (cause == 'Other' ) and (what == 'DALYs' ):
315
+ # Skip 'Other' when plotting DALYS as it's misleading. We don't have "Other" (non-modelled) causes
316
+ # of disability.
317
+ continue
318
+
314
319
vals = tot_outcomes_by_cause .loc [(slice (None ), cause ), ] / 1e3
315
320
316
321
x = vals .at [('mean' , cause ), 'GBD' ]
@@ -367,19 +372,22 @@ def shift_row_to_top(df, index_to_shift):
367
372
])
368
373
369
374
outcomes = outcome_by_age_pt ['GBD' ][("mean" )]
370
- fraction_causes_modelled = (1.0 - outcomes ['Other' ] / outcomes .sum (axis = 1 ))
375
+ fraction_causes_modelled_overall = (1.0 - outcomes ['Other' ].sum () / outcomes .sum ().sum ())
376
+ fraction_causes_modelled_by_sex_and_age = (1.0 - outcomes ['Other' ] / outcomes .sum (axis = 1 ))
371
377
fig , ax = plt .subplots ()
372
378
for sex in sexes :
373
- fraction_causes_modelled .loc [(sex , slice (None ))].plot (
379
+ fraction_causes_modelled_by_sex_and_age .loc [(sex , slice (None ))].plot (
374
380
ax = ax ,
375
381
color = get_color_cause_of_death_or_daly_label ('Other' ),
376
382
linestyle = ':' if sex == 'F' else '-' ,
377
383
label = sexname (sex ),
378
384
lw = 5 ,
379
385
)
380
- ax .legend ()
386
+ ax .axhline (fraction_causes_modelled_overall , color = 'b' ,
387
+ label = f'Overall: { round (100 * fraction_causes_modelled_overall )} %' )
388
+ ax .legend (loc = 'upper right' )
381
389
ax .set_ylim (0 , 1.0 )
382
- xticks = fraction_causes_modelled .index .levels [1 ]
390
+ xticks = fraction_causes_modelled_by_sex_and_age .index .levels [1 ]
383
391
ax .set_xticks (range (len (xticks )))
384
392
ax .set_xticklabels (xticks , rotation = 90 )
385
393
ax .grid (axis = 'y' )
@@ -392,6 +400,62 @@ def shift_row_to_top(df, index_to_shift):
392
400
plt .savefig (make_graph_file_name (f"C_{ what } _{ period } _coverage" ))
393
401
plt .close (fig )
394
402
403
+ # Describe the burden with respect to wealth quintile:
404
+ TARGET_PERIOD = (Date (2015 , 1 , 1 ), Date (2019 , 12 , 31 ))
405
+
406
+ def get_total_num_dalys_by_wealth_and_label (_df ):
407
+ """Return the total number of DALYS in the TARGET_PERIOD by wealth and cause label."""
408
+ wealth_cats = {5 : '0-19%' , 4 : '20-39%' , 3 : '40-59%' , 2 : '60-79%' , 1 : '80-100%' }
409
+
410
+ return _df \
411
+ .loc [_df ['year' ].between (* [d .year for d in TARGET_PERIOD ])] \
412
+ .drop (columns = ['date' , 'year' ]) \
413
+ .assign (
414
+ li_wealth = lambda x : x ['li_wealth' ].map (wealth_cats ).astype (
415
+ pd .CategoricalDtype (wealth_cats .values (), ordered = True )
416
+ )
417
+ ).melt (id_vars = ['li_wealth' ], var_name = 'label' ) \
418
+ .groupby (by = ['li_wealth' , 'label' ])['value' ] \
419
+ .sum ()
420
+
421
+ total_num_dalys_by_wealth_and_label = summarize (
422
+ extract_results (
423
+ results_folder ,
424
+ module = "tlo.methods.healthburden" ,
425
+ key = "dalys_by_wealth_stacked_by_age_and_time" ,
426
+ custom_generate_series = get_total_num_dalys_by_wealth_and_label ,
427
+ do_scaling = True ,
428
+ ),
429
+ collapse_columns = True ,
430
+ only_mean = True ,
431
+ ).unstack ()
432
+
433
+ format_to_plot = total_num_dalys_by_wealth_and_label \
434
+ .sort_index (axis = 0 ) \
435
+ .reindex (columns = CAUSE_OF_DEATH_OR_DALY_LABEL_TO_COLOR_MAP .keys (), fill_value = 0.0 ) \
436
+ .sort_index (axis = 1 , key = order_of_cause_of_death_or_daly_label )
437
+
438
+ fig , ax = plt .subplots ()
439
+ name_of_plot = 'DALYS by Wealth and Cause, 2015-2019'
440
+ (
441
+ format_to_plot / 1e6
442
+ ).plot .bar (stacked = True , ax = ax ,
443
+ color = [get_color_cause_of_death_or_daly_label (_label ) for _label in format_to_plot .columns ],
444
+ )
445
+ ax .axhline (0.0 , color = 'black' )
446
+ ax .set_title (name_of_plot )
447
+ ax .set_ylabel ('Number of DALYs Averted (/1e6)' )
448
+ ax .set_ylim (0 , 10 )
449
+ ax .set_xlabel ('Wealth Percentile' )
450
+ ax .grid ()
451
+ ax .spines ['top' ].set_visible (False )
452
+ ax .spines ['right' ].set_visible (False )
453
+ ax .legend (ncol = 3 , fontsize = 8 , loc = 'upper right' )
454
+ ax .legend ().set_visible (False )
455
+ fig .tight_layout ()
456
+ fig .savefig (make_graph_file_name (name_of_plot .replace (' ' , '_' )))
457
+ plt .close (fig )
458
+
395
459
# %% Make graphs for each of Deaths and DALYS for a specific period
396
460
# make_std_graphs(what='Deaths', period='2010-2014')
397
461
# make_std_graphs(what='DALYs', period='2010-2014')
0 commit comments