diff --git a/.readthedocs.yml b/.readthedocs.yml index 7ed86588a..9f258f6bb 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -21,7 +21,7 @@ formats: # Optionally set the version of Python and requirements required to build your docs python: - version: 3.7 + version: 3.8 install: - requirements: docs/requirements.txt - method: setuptools diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 874f06bc2..bccce8e12 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -23,8 +23,9 @@ This version contains a number of major updates. Note: this version requires Sci Highlights ^^^^^^^^^^ - **Parameters**: Default infection fatality ratio estimates have been updated in line with the latest literature. -- **Plotting**: Plotting defaults have been updated to support a wider range of systems, and users now have greater control over plotting options. -- **Webapp**: The webapp has been moved to a separate Python package, ``covasim_webapp`` (available `here `__) +- **Plotting**: Plotting defaults have been updated to support a wider range of systems, and users now have greater control over plotting and options. +- **New functions**: New methods have been added to display objects in different levels of detail; new methods have also been added for working with data, adding contacts, and analyzing multisims. +- **Webapp**: The webapp has been moved to a separate Python package, ``covasim_webapp`` (available `here `__). - **Documentation**: A comprehensive set of tutorials has been added, along with a glossary and FAQ; see https://docs.covasim.org or look in the ``docs/tutorials`` folder. Parameter updates @@ -55,25 +56,32 @@ Bugfixes ^^^^^^^^ - The ``quar_period`` argument is now correctly passed to the ``cv.contact_tracing()`` intervention. (Thanks to Scott McCrae for finding this bug.) - If the user supplies an incorrect type to ``cv.Layer.find_contacts()``, this is now caught and corrected. (Thanks to user sba5827 for finding this bug.) -- Non-string layer keys no longer raise an exception. +- Non-string ``Layer`` keys no longer raise an exception. +- The ``sim.compute_r_eff()`` error message now gives correct instructions (contributed by `Andrea Cattaneo `__). - Parallelization in Jupyter notebooks (e.g. ``msim.run()``) should now work without crashing. - If parallelization (e.g. ``msim.run()``) is called outside a ``main`` block on Windows, this leads to a cryptic error. This error is now caught more elegantly. - Interventions now print out with their actual name (previously they all printed out as ``InterventionDict``). - The keyword argument ``test_sensitivity`` for ``cv.test_prob()`` has been renamed ``sensitivity``, for consistency with ``cv.test_num()``. -Other changes -^^^^^^^^^^^^^ +New functions and methods +^^^^^^^^^^^^^^^^^^^^^^^^^ +- Sims, multisims, scenarios, and people objects now have ``disp()``, ``summarize()``, and ``brief()`` methods, which display full detail, moderate detail, and very little detail about each. If ``cv.options.verbose`` is 0, then ``brief()`` will be used to display objects; otherwise, ``disp()`` will be used. - Two new functions have been added, ``sim.get_intervention()`` and ``sim.get_analyzer()``. These act very similarly to e.g. ``sim.get_interventions()``, except they return the last matching intervention/analyzer, rather than returning a list of interventions/analyzers. -- There is a new verbose option: ``cv.Sim(verbose='brief').run()`` will print a single line of output when the sim finishes (namely, ``sim.brief()``). -- MultiSims now have a ``shrink()`` method, which shrinks both the base sim and the other sims they contain. MultiSims also have a ``brief()`` method, which prints out one line per sim (even briefer than ``msim.summarize()``). +- MultiSims now have a ``shrink()`` method, which shrinks both the base sim and the other sims they contain. - MultiSims also provide options to compute statistics using either the mean or the median; this can be done via the ``msim.reduce(use_mean=True)`` method. Two convenience methods, ``msim.mean()`` and ``msim.median()``, have also been added as shortcuts. +- Scenarios now have a ``scens.compare()`` method, which (like the multisim equivalent) creates a dataframe comparing results across scenarios. - Contacts now have new methods for handling layers, ``sim.people.contacts.add_layer()`` and ``sim.people.contacts.pop_layer()``. Additional validation on layers is also performed. -- There is a new function, ``cv.data.get_valid_locations()``, that lists locations for which demographic data are available. +- There is a new function, ``cv.data.show_locations()``, that lists locations for which demographic data are available. You can also now edit the data dictionaries directly, by modifying e.g. ``cv.data.country_age_data.data`` (suggested by `Andrea Cattaneo `__). + +Other changes +^^^^^^^^^^^^^ +- There is a new verbose option for sims: ``cv.Sim(verbose='brief').run()`` will print a single line of output when the sim finishes (namely, ``sim.brief()``). - The argument ``n_cpus`` can now be supplied directly to ``cv.multirun()`` and ``msim.run()``. - The types ``cv.default_float`` and ``cv.default_int`` are now available at the top level (previously they had to be accessed by e.g. ``cv.defaults.default_float``). - Transmission trees now contain additional output; after ``tt = sim.make_transtree()``, a dataframe of key results is contained in ``tt.df``. - The default number of seed infections has been changed from 10 to 20 for greater numerical stability. (Note that this placeholder value should be overridden for all actual applications.) - ``sim.run()`` no longer returns the results object by default (if you want it, set ``output=True``). +- A migrations module has been added (in ``misc.py``). Objects are now automatically migrated to the current version of Covasim whene loaded The function ``cv.migrate()`` can also be called explicitly on objects if needed. Documentation ^^^^^^^^^^^^^ @@ -86,7 +94,7 @@ Regression information - Any scripts that used ``results = sim.run()`` will need to be updated to ``results = sim.run(output=True)``. - Any scripts that passed formatting options directly to plots should set these as options instead; e.g. ``sim.plot(font_size=18)`` should now be ``cv.options.set(font_size=18); sim.plot()``. - Any custom interventions that defined a custom ``plot()`` method should use ``plot_interventions()`` instead. -- *GitHub info*: PR `738 `__ +- *GitHub info*: PRs `738 `__, `740 `__ diff --git a/README.rst b/README.rst index 9a8fffef5..efb2a42c7 100644 --- a/README.rst +++ b/README.rst @@ -121,7 +121,7 @@ The structure of the ``covasim`` folder is as follows, roughly in the order in w * ``requirements.py``: A simple module to check that imports succeeded, and turn off features if they didn't. * ``utils.py``: Functions for choosing random numbers, many based on Numba, plus other helper functions. * ``misc.py``: Miscellaneous helper functions. -* ``options.py``: User-customizable options for Covasim (e.g. default font size). +* ``settings.py``: User-customizable options for Covasim (e.g. default font size). * ``defaults.py``: The default colors, plots, etc. used by Covasim. * ``parameters.py``: Functions for creating the parameters dictionary and loading the input data. * ``plotting.py``: Plotting scripts, including Plotly graphs for the webapp (used in other Covasim classes, and hence defined first). diff --git a/covasim/base.py b/covasim/base.py index 05b9aedf9..14f9f90f7 100644 --- a/covasim/base.py +++ b/covasim/base.py @@ -13,6 +13,7 @@ from . import misc as cvm from . import defaults as cvd from . import parameters as cvpar +from .settings import options as cvo # Specify all externally visible classes this file defines __all__ = ['ParsObj', 'Result', 'BaseSim', 'BasePeople', 'Person', 'FlexDict', 'Contacts', 'Layer'] @@ -20,7 +21,50 @@ #%% Define simulation classes -class ParsObj(sc.prettyobj): +class FlexPretty(sc.prettyobj): + ''' + A class that by default changes the display type depending on the current level + of verbosity. + ''' + + def __repr__(self): + ''' Set display options based on current level of verbosity ''' + try: + if cvo['verbose']: + string = self._disp() + else: + string = self._brief() + except Exception as E: + string = sc.objectid(self) + string += f'Warning, something went wrong printing object:\n{str(E)}' + return string + + def _disp(self): + ''' Verbose output -- use Sciris' pretty repr by default ''' + return sc.prepr(self) + + def disp(self, output=False): + ''' Print or output verbose representation of the object ''' + string = self._disp() + if not output: + print(string) + else: + return string + + def _brief(self): + ''' Brief output -- use a one-line output, a la Python's default ''' + return sc.objectid(self) + + def brief(self, output=False): + ''' Print or output a brief representation of the object ''' + string = self._brief() + if not output: + print(string) + else: + return string + + +class ParsObj(FlexPretty): ''' A class based around performing operations on a self.pars dict. ''' @@ -29,6 +73,7 @@ def __init__(self, pars): self.update_pars(pars, create=True) return + def __getitem__(self, key): ''' Allow sim['par_name'] instead of sim.pars['par_name'] ''' try: @@ -48,6 +93,9 @@ def __setitem__(self, key, value): raise sc.KeyNotFoundError(errormsg) return + + + def update_pars(self, pars=None, create=False): ''' Update internal dict with new pars. @@ -129,6 +177,14 @@ def npts(self): return len(self.values) +def set_metadata(obj): + ''' Set standard metadata for an object ''' + obj.created = sc.now() + obj.version = cvv.__version__ + obj.git_info = cvm.git_info() + return + + class BaseSim(ParsObj): ''' The BaseSim class stores various methods useful for the Sim that are not directly @@ -141,6 +197,50 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Initialize and set the parameters as attributes return + + def _disp(self): + ''' + Print a verbose display of the sim object. Used by repr(). See sim.disp() + for the user version. Equivalent to sc.prettyobj(). + ''' + return sc.prepr(self) + + + def _brief(self): + ''' + Return a one-line description of a sim -- used internally and by repr(); + see sim.brief() for the user version. + ''' + # Try to get a detailed description of the sim... + try: + if self.results_ready: + infections = self.summary['cum_infections'] + deaths = self.summary['cum_deaths'] + results = f'{infections:n}⚙, {deaths:n}☠' + else: + results = 'not run' + + # Set label string + labelstr = f'"{self.label}"' if self.label else '' + + start = sc.date(self['start_day'], as_date=False) + if self['end_day']: + end = sc.date(self['end_day'], as_date=False) + else: + end = sc.date(self['n_days'], start_date=start) + + pop_size = self['pop_size'] + pop_type = self['pop_type'] + string = f'Sim({labelstr}; {start} to {end}; pop: {pop_size:n} {pop_type}; epi: {results})' + + # ...but if anything goes wrong, return the default with a warning + except Exception as E: + string = sc.objectid(self) + string += f'Warning, sim appears to be malformed:\n{str(E)}' + + return string + + def update_pars(self, pars=None, create=False, **kwargs): ''' Ensure that metaparameters get used properly before being updated ''' pars = sc.mergedicts(pars, kwargs) @@ -153,16 +253,12 @@ def update_pars(self, pars=None, create=False, **kwargs): return - def set_metadata(self, simfile, label): + def set_metadata(self, simfile): ''' Set the metadata for the simulation -- creation time and filename ''' - self.created = sc.now() - self.version = cvv.__version__ - self.git_info = cvm.git_info() + set_metadata(self) if simfile is None: datestr = sc.getdate(obj=self.created, dateformat='%Y-%b-%d_%H.%M.%S') self.simfile = f'covasim_{datestr}.sim' - if label is not None: - self.label = label return @@ -686,7 +782,7 @@ def get_analyzer(self, label=None, partial=False, first=False, die=True): #%% Define people classes -class BasePeople(sc.prettyobj): +class BasePeople(FlexPretty): ''' A class to handle all the boilerplate for people -- note that as with the BaseSim vs Sim classes, everything interesting happens in the People class, @@ -744,6 +840,25 @@ def __add__(self, people2): return newpeople + def _brief(self): + ''' + Return a one-line description of the people -- used internally and by repr(); + see people.brief() for the user version. + ''' + try: + layerstr = ', '.join([str(k) for k in self.layer_keys()]) + string = f'People(n={len(self):0n}; layers: {layerstr})' + except Exception as E: + string = sc.objectid(self) + string += f'Warning, multisim appears to be malformed:\n{str(E)}' + return string + + + def summarize(self, output=False): + ''' Print a summary of the people -- same as brief ''' + return self.brief(output=output) + + def set(self, key, value, die=True): ''' Ensure sizes and dtypes match ''' current = self[key] diff --git a/covasim/data/country_age_data.py b/covasim/data/country_age_data.py index 446e5d5ce..421980b26 100644 --- a/covasim/data/country_age_data.py +++ b/covasim/data/country_age_data.py @@ -1,1829 +1,1828 @@ -def get(): - ''' - This is the following file: +''' +This is the following file: - https://github.com/neherlab/covid19_scenarios/blob/master/src/assets/data/country_age_distribution.json +https://github.com/neherlab/covid19_scenarios/blob/master/src/assets/data/country_age_distribution.json - expressed as a function. - ''' - output = { - 'Afghanistan': {'0-9': 11088731, - '10-19': 9821561, - '20-29': 7035871, - '30-39': 4534646, - '40-49': 2963460, - '50-59': 1840199, - '60-69': 1057497, - '70-79': 480455, - '80+': 105925}, - 'Albania': {'0-9': 333832, - '10-19': 361777, - '20-29': 472678, - '30-39': 390771, - '40-49': 323020, - '50-59': 386091, - '60-69': 330244, - '70-79': 194668, - '80+': 84716}, - 'Algeria': {'0-9': 9677492, - '10-19': 6731745, - '20-29': 6573711, - '30-39': 7275234, - '40-49': 5448620, - '50-59': 3800054, - '60-69': 2530543, - '70-79': 1237832, - '80+': 575811}, - 'Angola': {'0-9': 10899167, - '10-19': 7881777, - '20-29': 5306039, - '30-39': 3699729, - '40-49': 2412736, - '50-59': 1464604, - '60-69': 785896, - '70-79': 331730, - '80+': 84594}, - 'Antigua and Barbuda': {'0-9': 14582, - '10-19': 13868, - '20-29': 14895, - '30-39': 14095, - '40-49': 13860, - '50-59': 12832, - '60-69': 8042, - '70-79': 4101, - '80+': 1654}, - 'Argentina': {'0-9': 7446465, - '10-19': 7136712, - '20-29': 6997584, - '30-39': 6441412, - '40-49': 5727746, - '50-59': 4424939, - '60-69': 3528743, - '70-79': 2300637, - '80+': 1191536}, - 'Armenia': {'0-9': 418860, - '10-19': 368930, - '20-29': 408926, - '30-39': 503954, - '40-49': 353090, - '50-59': 362654, - '60-69': 328401, - '70-79': 126744, - '80+': 91684}, - 'Aruba': {'0-9': 11758, - '10-19': 14010, - '20-29': 14980, - '30-39': 11241, - '40-49': 14271, - '50-59': 17207, - '60-69': 13753, - '70-79': 6956, - '80+': 2590}, - 'Australia': {'0-9': 3308972, - '10-19': 3130480, - '20-29': 3375453, - '30-39': 3718346, - '40-49': 3306061, - '50-59': 3107734, - '60-69': 2651187, - '70-79': 1846377, - '80+': 1055274}, - 'Austria': {'0-9': 874182, - '10-19': 876207, - '20-29': 1115378, - '30-39': 1243414, - '40-49': 1178265, - '50-59': 1407001, - '60-69': 1033318, - '70-79': 790436, - '80+': 488197}, - 'Azerbaijan': {'0-9': 1686038, - '10-19': 1335455, - '20-29': 1608982, - '30-39': 1766690, - '40-49': 1280804, - '50-59': 1281076, - '60-69': 804312, - '70-79': 242762, - '80+': 133058}, - 'Bahamas': {'0-9': 53654, - '10-19': 63795, - '20-29': 66571, - '30-39': 55456, - '40-49': 56498, - '50-59': 49219, - '60-69': 29427, - '70-79': 13644, - '80+': 4980}, - 'Bahrain': {'0-9': 218134, - '10-19': 181855, - '20-29': 306667, - '30-39': 507735, - '40-49': 256720, - '50-59': 140231, - '60-69': 66573, - '70-79': 17815, - '80+': 5845}, - 'Bangladesh': {'0-9': 28972611, - '10-19': 30674421, - '20-29': 29765032, - '30-39': 26511633, - '40-49': 20651269, - '50-59': 15005706, - '60-69': 7296839, - '70-79': 4095813, - '80+': 1716059}, - 'Barbados': {'0-9': 30617, - '10-19': 36514, - '20-29': 37578, - '30-39': 37124, - '40-49': 39068, - '50-59': 39936, - '60-69': 33573, - '70-79': 20154, - '80+': 12811}, - 'Belarus': {'0-9': 1143840, - '10-19': 928884, - '20-29': 1077804, - '30-39': 1530347, - '40-49': 1285399, - '50-59': 1345792, - '60-69': 1243251, - '70-79': 525562, - '80+': 368444}, - 'Belgium': {'0-9': 1302703, - '10-19': 1312253, - '20-29': 1386087, - '30-39': 1504000, - '40-49': 1518439, - '50-59': 1598741, - '60-69': 1369875, - '70-79': 939415, - '80+': 658110}, - 'Belize': {'0-9': 78107, - '10-19': 77850, - '20-29': 75822, - '30-39': 59711, - '40-49': 43959, - '50-59': 31811, - '60-69': 17817, - '70-79': 8310, - '80+': 4240}, - 'Benin': {'0-9': 3596952, - '10-19': 2779488, - '20-29': 2061769, - '30-39': 1436440, - '40-49': 981831, - '50-59': 650680, - '60-69': 379184, - '70-79': 184835, - '80+': 52021}, - 'Bhutan': {'0-9': 125825, - '10-19': 135992, - '20-29': 153315, - '30-39': 138679, - '40-49': 89605, - '50-59': 59011, - '60-69': 36910, - '70-79': 22235, - '80+': 10036}, - 'Bolivia (Plurinational State of)': {'0-9': 2364587, - '10-19': 2297693, - '20-29': 2039536, - '30-39': 1639098, - '40-49': 1238341, - '50-59': 883592, - '60-69': 615318, - '70-79': 391940, - '80+': 202916}, - 'Bosnia and Herzegovina': {'0-9': 295215, - '10-19': 346276, - '20-29': 403273, - '30-39': 458386, - '40-49': 447738, - '50-59': 500181, - '60-69': 463795, - '70-79': 242499, - '80+': 123456}, - 'Botswana': {'0-9': 539004, - '10-19': 472033, - '20-29': 402508, - '30-39': 365289, - '40-49': 261017, - '50-59': 146580, - '60-69': 104252, - '70-79': 48560, - '80+': 12384}, - 'Brazil': {'0-9': 29076912, - '10-19': 31160447, - '20-29': 34104644, - '30-39': 34476764, - '40-49': 29462008, - '50-59': 24421199, - '60-69': 16896864, - '70-79': 8801551, - '80+': 4159028}, - 'Brunei Darussalam': {'0-9': 66355, - '10-19': 65082, - '20-29': 69697, - '30-39': 76569, - '40-49': 68004, - '50-59': 50218, - '60-69': 28512, - '70-79': 9570, - '80+': 3471}, - 'Bulgaria': {'0-9': 649382, - '10-19': 685881, - '20-29': 689917, - '30-39': 957591, - '40-49': 1061986, - '50-59': 944703, - '60-69': 922593, - '70-79': 710368, - '80+': 326024}, - 'Burkina Faso': {'0-9': 6552186, - '10-19': 5029543, - '20-29': 3508067, - '30-39': 2428031, - '40-49': 1587132, - '50-59': 977489, - '60-69': 538877, - '70-79': 234236, - '80+': 47712}, - 'Burundi': {'0-9': 3872449, - '10-19': 2725292, - '20-29': 2029583, - '30-39': 1539545, - '40-49': 747634, - '50-59': 491973, - '60-69': 339630, - '70-79': 112127, - '80+': 32551}, - 'Cabo Verde': {'0-9': 105077, - '10-19': 99937, - '20-29': 97847, - '30-39': 98288, - '40-49': 64905, - '50-59': 47913, - '60-69': 26368, - '70-79': 9054, - '80+': 6598}, - 'Cambodia': {'0-9': 3530588, - '10-19': 3100069, - '20-29': 3117605, - '30-39': 2889268, - '40-49': 1429088, - '50-59': 1387484, - '60-69': 816774, - '70-79': 352443, - '80+': 95646}, - 'Cameroon': {'0-9': 7846025, - '10-19': 6176460, - '20-29': 4551789, - '30-39': 3399844, - '40-49': 2141843, - '50-59': 1288476, - '60-69': 733298, - '70-79': 332733, - '80+': 75395}, - 'Canada': {'0-9': 3970918, - '10-19': 3971318, - '20-29': 5096615, - '30-39': 5278663, - '40-49': 4846667, - '50-59': 5182430, - '60-69': 4712746, - '70-79': 3018677, - '80+': 1664120}, - 'Central African Republic': {'0-9': 1435610, - '10-19': 1264610, - '20-29': 839989, - '30-39': 501334, - '40-49': 339531, - '50-59': 232597, - '60-69': 139061, - '70-79': 61505, - '80+': 15530}, - 'Chad': {'0-9': 5452555, - '10-19': 4038729, - '20-29': 2781016, - '30-39': 1769644, - '40-49': 1082834, - '50-59': 654647, - '60-69': 417351, - '70-79': 180661, - '80+': 48427}, - 'Channel Islands': {'0-9': 17565, - '10-19': 17778, - '20-29': 21767, - '30-39': 23888, - '40-49': 24915, - '50-59': 26180, - '60-69': 20014, - '70-79': 13295, - '80+': 8461}, - 'Chile': {'0-9': 2428078, - '10-19': 2493875, - '20-29': 2995538, - '30-39': 2945403, - '40-49': 2578406, - '50-59': 2352271, - '60-69': 1791785, - '70-79': 993127, - '80+': 537718}, - 'China': {'0-9': 170667621, - '10-19': 166604608, - '20-29': 185147173, - '30-39': 228830425, - '40-49': 216111764, - '50-59': 222185873, - '60-69': 151663904, - '70-79': 71494306, - '80+': 26618102}, - 'China, Hong Kong Special Administrative Region': {'0-9': 664195, - '10-19': 552658, - '20-29': 867629, - '30-39': 1122165, - '40-49': 1129131, - '50-59': 1207906, - '60-69': 1048879, - '70-79': 525082, - '80+': 379336}, - 'China, Macao Special Administrative Region': {'0-9': 68816, - '10-19': 46834, - '20-29': 88333, - '30-39': 129800, - '40-49': 93400, - '50-59': 99614, - '60-69': 78993, - '70-79': 29881, - '80+': 13664}, - 'Colombia': {'0-9': 7414157, - '10-19': 8119877, - '20-29': 8847062, - '30-39': 7810299, - '40-49': 6450787, - '50-59': 5543982, - '60-69': 3771360, - '70-79': 1979762, - '80+': 945605}, - 'Comoros': {'0-9': 237638, - '10-19': 191272, - '20-29': 150847, - '30-39': 117375, - '40-49': 77037, - '50-59': 50890, - '60-69': 29657, - '70-79': 11660, - '80+': 3225}, - 'Congo': {'0-9': 1592333, - '10-19': 1257962, - '20-29': 874259, - '30-39': 680079, - '40-49': 535815, - '50-59': 327893, - '60-69': 164736, - '70-79': 69397, - '80+': 15613}, - 'Costa Rica': {'0-9': 705597, - '10-19': 718839, - '20-29': 824456, - '30-39': 825655, - '40-49': 650563, - '50-59': 602394, - '60-69': 423012, - '70-79': 230865, - '80+': 112737}, - 'Croatia': {'0-9': 385776, - '10-19': 408108, - '20-29': 472201, - '30-39': 539290, - '40-49': 557001, - '50-59': 581382, - '60-69': 565376, - '70-79': 361956, - '80+': 234177}, - 'Cuba': {'0-9': 1199375, - '10-19': 1246736, - '20-29': 1421019, - '30-39': 1523032, - '40-49': 1561981, - '50-59': 1967294, - '60-69': 1174022, - '70-79': 804207, - '80+': 428950}, - 'Curaçao': {'0-9': 19332, - '10-19': 21569, - '20-29': 19539, - '30-39': 18724, - '40-49': 20279, - '50-59': 24425, - '60-69': 20705, - '70-79': 13003, - '80+': 6517}, - 'Cyprus': {'0-9': 132391, - '10-19': 141658, - '20-29': 191801, - '30-39': 188388, - '40-49': 166627, - '50-59': 147538, - '60-69': 120401, - '70-79': 78681, - '80+': 39873}, - 'Czechia': {'0-9': 1113645, - '10-19': 1061333, - '20-29': 1105336, - '30-39': 1478211, - '40-49': 1798356, - '50-59': 1351269, - '60-69': 1324617, - '70-79': 1031099, - '80+': 445115}, - 'Côte d’Ivoire': {'0-9': 7750285, - '10-19': 6104859, - '20-29': 4660993, - '30-39': 3172218, - '40-49': 2117549, - '50-59': 1337227, - '60-69': 822065, - '70-79': 341744, - '80+': 71333}, - "Democratic People's Republic of Korea": {'0-9': 3430376, - '10-19': 3561227, - '20-29': 3925716, - '30-39': 3641896, - '40-49': 3714317, - '50-59': 3622786, - '60-69': 2134680, - '70-79': 1303957, - '80+': 443861}, - 'Democratic Republic of the Congo': {'0-9': 29487305, - '10-19': 21000019, - '20-29': 14169239, - '30-39': 9762333, - '40-49': 6605529, - '50-59': 4347003, - '60-69': 2585842, - '70-79': 1268687, - '80+': 335446}, - 'Denmark': {'0-9': 606028, - '10-19': 675946, - '20-29': 775962, - '30-39': 672290, - '40-49': 738209, - '50-59': 810126, - '60-69': 654530, - '70-79': 586139, - '80+': 272972}, - 'Djibouti': {'0-9': 197110, - '10-19': 179320, - '20-29': 177326, - '30-39': 162418, - '40-49': 120923, - '50-59': 78074, - '60-69': 44336, - '70-79': 22330, - '80+': 6163}, - 'Dominican Republic': {'0-9': 1999349, - '10-19': 1935877, - '20-29': 1854317, - '30-39': 1564383, - '40-49': 1274489, - '50-59': 1014335, - '60-69': 682138, - '70-79': 341500, - '80+': 181522}, - 'Ecuador': {'0-9': 3277730, - '10-19': 3115981, - '20-29': 3036186, - '30-39': 2592840, - '40-49': 2088240, - '50-59': 1591141, - '60-69': 1087740, - '70-79': 570125, - '80+': 283071}, - 'Egypt': {'0-9': 25028540, - '10-19': 18385431, - '20-29': 16511130, - '30-39': 15198348, - '40-49': 10948603, - '50-59': 7844894, - '60-69': 5122656, - '70-79': 2530981, - '80+': 763821}, - 'El Salvador': {'0-9': 1146823, - '10-19': 1165823, - '20-29': 1215815, - '30-39': 882443, - '40-49': 725144, - '50-59': 568072, - '60-69': 406296, - '70-79': 248393, - '80+': 127396}, - 'Equatorial Guinea': {'0-9': 371662, - '10-19': 265295, - '20-29': 286389, - '30-39': 248982, - '40-49': 115361, - '50-59': 62216, - '60-69': 34879, - '70-79': 14719, - '80+': 3482}, - 'Eritrea': {'0-9': 971768, - '10-19': 860627, - '20-29': 572233, - '30-39': 460764, - '40-49': 280838, - '50-59': 171949, - '60-69': 128327, - '70-79': 77079, - '80+': 22836}, - 'Estonia': {'0-9': 143661, - '10-19': 137487, - '20-29': 145554, - '30-39': 193631, - '40-49': 184936, - '50-59': 165282, - '60-69': 169473, - '70-79': 107430, - '80+': 79081}, - 'Eswatini': {'0-9': 286620, - '10-19': 277020, - '20-29': 212889, - '30-39': 161329, - '40-49': 104399, - '50-59': 51716, - '60-69': 36524, - '70-79': 22581, - '80+': 7086}, - 'Ethiopia': {'0-9': 32037548, - '10-19': 26828994, - '20-29': 21439043, - '30-39': 13792878, - '40-49': 9038652, - '50-59': 5704067, - '60-69': 3624557, - '70-79': 1929368, - '80+': 568479}, - 'Fiji': {'0-9': 177143, - '10-19': 158135, - '20-29': 141943, - '30-39': 134953, - '40-49': 106524, - '50-59': 91436, - '60-69': 57120, - '70-79': 23633, - '80+': 5558}, - 'Finland': {'0-9': 568681, - '10-19': 606659, - '20-29': 672353, - '30-39': 706581, - '40-49': 659560, - '50-59': 720555, - '60-69': 712327, - '70-79': 582988, - '80+': 311016}, - 'France': {'0-9': 7527473, - '10-19': 7883476, - '20-29': 7371030, - '30-39': 8011050, - '40-49': 8325670, - '50-59': 8635055, - '60-69': 7764785, - '70-79': 5727704, - '80+': 4027268}, - 'French Guiana': {'0-9': 66122, - '10-19': 57555, - '20-29': 46109, - '30-39': 38719, - '40-49': 36992, - '50-59': 26711, - '60-69': 17226, - '70-79': 7221, - '80+': 2027}, - 'French Polynesia': {'0-9': 39637, - '10-19': 44133, - '20-29': 40379, - '30-39': 43366, - '40-49': 39589, - '50-59': 35650, - '60-69': 23042, - '70-79': 10823, - '80+': 4289}, - 'Gabon': {'0-9': 600005, - '10-19': 422773, - '20-29': 367412, - '30-39': 350071, - '40-49': 232167, - '50-59': 134150, - '60-69': 71303, - '70-79': 36691, - '80+': 11162}, - 'Gambia': {'0-9': 762307, - '10-19': 556857, - '20-29': 429180, - '30-39': 283130, - '40-49': 174068, - '50-59': 115915, - '60-69': 59281, - '70-79': 30007, - '80+': 5923}, - 'Georgia': {'0-9': 553163, - '10-19': 471056, - '20-29': 500696, - '30-39': 565077, - '40-49': 517944, - '50-59': 523623, - '60-69': 459856, - '70-79': 248784, - '80+': 148968}, - 'Germany': {'0-9': 7880902, - '10-19': 7930616, - '20-29': 9377359, - '30-39': 10872019, - '40-49': 10243351, - '50-59': 13488393, - '60-69': 10644140, - '70-79': 7471414, - '80+': 5875748}, - 'Ghana': {'0-9': 8057871, - '10-19': 6616719, - '20-29': 5398591, - '30-39': 4190417, - '40-49': 3031249, - '50-59': 2134980, - '60-69': 1091069, - '70-79': 456786, - '80+': 95258}, - 'Greece': {'0-9': 881128, - '10-19': 1068855, - '20-29': 1057214, - '30-39': 1336517, - '40-49': 1574408, - '50-59': 1505692, - '60-69': 1257161, - '70-79': 956084, - '80+': 785994}, - 'Grenada': {'0-9': 18132, - '10-19': 16137, - '20-29': 18288, - '30-39': 18211, - '40-49': 12874, - '50-59': 12146, - '60-69': 9573, - '70-79': 4789, - '80+': 2373}, - 'Guadeloupe': {'0-9': 44992, - '10-19': 58514, - '20-29': 46875, - '30-39': 33762, - '40-49': 49307, - '50-59': 62202, - '60-69': 50569, - '70-79': 32942, - '80+': 20961}, - 'Guam': {'0-9': 26981, - '10-19': 27159, - '20-29': 27031, - '30-39': 21837, - '40-49': 19935, - '50-59': 20162, - '60-69': 14330, - '70-79': 7777, - '80+': 3563}, - 'Guatemala': {'0-9': 4047466, - '10-19': 3871605, - '20-29': 3413158, - '30-39': 2532063, - '40-49': 1701991, - '50-59': 1053821, - '60-69': 718853, - '70-79': 382505, - '80+': 194106}, - 'Guinea': {'0-9': 3965625, - '10-19': 3199454, - '20-29': 2365739, - '30-39': 1470866, - '40-49': 898439, - '50-59': 614523, - '60-69': 408149, - '70-79': 171250, - '80+': 38750}, - 'Guinea-Bissau': {'0-9': 582349, - '10-19': 450031, - '20-29': 342383, - '30-39': 254507, - '40-49': 156574, - '50-59': 92190, - '60-69': 60417, - '70-79': 24637, - '80+': 4913}, - 'Guyana': {'0-9': 147626, - '10-19': 145351, - '20-29': 145302, - '30-39': 93113, - '40-49': 90525, - '50-59': 79336, - '60-69': 51355, - '70-79': 22936, - '80+': 11008}, - 'Haiti': {'0-9': 2500777, - '10-19': 2346528, - '20-29': 2044459, - '30-39': 1731657, - '40-49': 1106487, - '50-59': 789624, - '60-69': 523931, - '70-79': 260217, - '80+': 98848}, - 'Honduras': {'0-9': 2005992, - '10-19': 2064637, - '20-29': 1905416, - '30-39': 1470935, - '40-49': 1047736, - '50-59': 680012, - '60-69': 420079, - '70-79': 205312, - '80+': 104488}, - 'Hungary': {'0-9': 908567, - '10-19': 969206, - '20-29': 1151691, - '30-39': 1257140, - '40-49': 1588213, - '50-59': 1201387, - '60-69': 1306434, - '70-79': 846578, - '80+': 431135}, - 'Iceland': {'0-9': 43070, - '10-19': 44710, - '20-29': 47796, - '30-39': 46869, - '40-49': 42966, - '50-59': 42112, - '60-69': 37536, - '70-79': 23413, - '80+': 12771}, - 'India': {'0-9': 234861633, - '10-19': 252201517, - '20-29': 239902073, - '30-39': 215636276, - '40-49': 169660176, - '50-59': 128132229, - '60-69': 87150813, - '70-79': 39175398, - '80+': 13284270}, - 'Indonesia': {'0-9': 47956444, - '10-19': 46303002, - '20-29': 43571426, - '30-39': 41166623, - '40-49': 37846723, - '50-59': 29155099, - '60-69': 17531210, - '70-79': 7574475, - '80+': 2418613}, - 'Iran (Islamic Republic of)': {'0-9': 14565855, - '10-19': 11747928, - '20-29': 12342906, - '30-39': 16739444, - '40-49': 11655616, - '50-59': 8295330, - '60-69': 5396906, - '70-79': 2354607, - '80+': 894357}, - 'Iraq': {'0-9': 10610228, - '10-19': 8710756, - '20-29': 7165589, - '30-39': 5403684, - '40-49': 3936617, - '50-59': 2341151, - '60-69': 1292393, - '70-79': 573718, - '80+': 188357}, - 'Ireland': {'0-9': 671943, - '10-19': 668746, - '20-29': 567336, - '30-39': 695926, - '40-49': 763226, - '50-59': 600934, - '60-69': 480783, - '70-79': 330663, - '80+': 158229}, - 'Israel': {'0-9': 1671094, - '10-19': 1405063, - '20-29': 1196974, - '30-39': 1122245, - '40-49': 1040178, - '50-59': 795495, - '60-69': 703645, - '70-79': 459660, - '80+': 261181}, - 'Italy': {'0-9': 4994996, - '10-19': 5733447, - '20-29': 6103437, - '30-39': 6998434, - '40-49': 9022004, - '50-59': 9567192, - '60-69': 7484860, - '70-79': 6028907, - '80+': 4528548}, - 'Jamaica': {'0-9': 464791, - '10-19': 466600, - '20-29': 515497, - '30-39': 443384, - '40-49': 357431, - '50-59': 320532, - '60-69': 214542, - '70-79': 119523, - '80+': 58867}, - 'Japan': {'0-9': 10179968, - '10-19': 11267171, - '20-29': 12147325, - '30-39': 14455415, - '40-49': 18473078, - '50-59': 16541516, - '60-69': 15875236, - '70-79': 16185375, - '80+': 11351377}, - 'Jordan': {'0-9': 2212563, - '10-19': 2179854, - '20-29': 1802535, - '30-39': 1490607, - '40-49': 1141344, - '50-59': 755593, - '60-69': 366276, - '70-79': 190748, - '80+': 63614}, - 'Kazakhstan': {'0-9': 3868009, - '10-19': 2720923, - '20-29': 2573190, - '30-39': 2993496, - '40-49': 2286423, - '50-59': 2039442, - '60-69': 1438908, - '70-79': 552508, - '80+': 303808}, - 'Kenya': {'0-9': 14013908, - '10-19': 12746880, - '20-29': 9594275, - '30-39': 7470149, - '40-49': 4903045, - '50-59': 2805603, - '60-69': 1518824, - '70-79': 574335, - '80+': 144277}, - 'Kiribati': {'0-9': 29464, - '10-19': 23634, - '20-29': 20524, - '30-39': 16606, - '40-49': 11169, - '50-59': 9988, - '60-69': 5143, - '70-79': 2331, - '80+': 590}, - 'Kosovo': {'0-9': 294038, - '10-19': 306895, - '20-29': 299672, - '30-39': 237846, - '40-49': 228757, - '50-59': 189740, - '60-69': 127956, - '70-79': 71350, - '80+': 32684}, - 'Kuwait': {'0-9': 608328, - '10-19': 533225, - '20-29': 444882, - '30-39': 878557, - '40-49': 965368, - '50-59': 561299, - '60-69': 220263, - '70-79': 48552, - '80+': 10095}, - 'Kyrgyzstan': {'0-9': 1529449, - '10-19': 1100700, - '20-29': 1082940, - '30-39': 1014707, - '40-49': 686437, - '50-59': 581436, - '60-69': 363825, - '70-79': 111215, - '80+': 53484}, - "Lao People's Democratic Republic": {'0-9': 1566742, - '10-19': 1466251, - '20-29': 1362624, - '30-39': 1086530, - '40-49': 772683, - '50-59': 526580, - '60-69': 317973, - '70-79': 136165, - '80+': 40012}, - 'Latvia': {'0-9': 207770, - '10-19': 188723, - '20-29': 188221, - '30-39': 263219, - '40-49': 253889, - '50-59': 264241, - '60-69': 250143, - '70-79': 162705, - '80+': 107287}, - 'Lebanon': {'0-9': 1152160, - '10-19': 1134997, - '20-29': 1176573, - '30-39': 1009647, - '40-49': 862746, - '50-59': 724776, - '60-69': 447766, - '70-79': 211573, - '80+': 105207}, - 'Lesotho': {'0-9': 478747, - '10-19': 428822, - '20-29': 395193, - '30-39': 327280, - '40-49': 210253, - '50-59': 140769, - '60-69': 96810, - '70-79': 48309, - '80+': 16066}, - 'Liberia': {'0-9': 1418817, - '10-19': 1175027, - '20-29': 840855, - '30-39': 629808, - '40-49': 444196, - '50-59': 283827, - '60-69': 168470, - '70-79': 76455, - '80+': 20226}, - 'Libya': {'0-9': 1285422, - '10-19': 1185747, - '20-29': 1095417, - '30-39': 1163468, - '40-49': 1049198, - '50-59': 617153, - '60-69': 284261, - '70-79': 138926, - '80+': 51700}, - 'Lithuania': {'0-9': 300673, - '10-19': 242840, - '20-29': 316879, - '30-39': 337567, - '40-49': 355907, - '50-59': 420559, - '60-69': 352811, - '70-79': 223282, - '80+': 171771}, - 'Luxembourg': {'0-9': 65905, - '10-19': 65903, - '20-29': 85535, - '30-39': 98316, - '40-49': 94599, - '50-59': 90857, - '60-69': 62121, - '70-79': 37874, - '80+': 24867}, - 'Madagascar': {'0-9': 7762934, - '10-19': 6342928, - '20-29': 4898736, - '30-39': 3370908, - '40-49': 2387857, - '50-59': 1539765, - '60-69': 915207, - '70-79': 359863, - '80+': 112819}, - 'Malawi': {'0-9': 5662517, - '10-19': 4738054, - '20-29': 3377519, - '30-39': 2286024, - '40-49': 1436743, - '50-59': 846147, - '60-69': 480251, - '70-79': 244240, - '80+': 58457}, - 'Malaysia': {'0-9': 5143191, - '10-19': 5115769, - '20-29': 5770367, - '30-39': 5651218, - '40-49': 3990530, - '50-59': 3146037, - '60-69': 2151364, - '70-79': 1025182, - '80+': 372341}, - 'Maldives': {'0-9': 72820, - '10-19': 59438, - '20-29': 139684, - '30-39': 137607, - '40-49': 64647, - '50-59': 35317, - '60-69': 18164, - '70-79': 8467, - '80+': 4400}, - 'Mali': {'0-9': 6760318, - '10-19': 5009462, - '20-29': 3203821, - '30-39': 2160455, - '40-49': 1485960, - '50-59': 849115, - '60-69': 501293, - '70-79': 231083, - '80+': 49326}, - 'Malta': {'0-9': 43103, - '10-19': 40926, - '20-29': 55214, - '30-39': 65354, - '40-49': 59448, - '50-59': 53214, - '60-69': 57678, - '70-79': 45166, - '80+': 21440}, - 'Martinique': {'0-9': 35951, - '10-19': 47121, - '20-29': 41372, - '30-39': 34103, - '40-49': 44188, - '50-59': 62795, - '60-69': 52466, - '70-79': 33674, - '80+': 23595}, - 'Mauritania': {'0-9': 1307828, - '10-19': 1007554, - '20-29': 787903, - '30-39': 619780, - '40-49': 422633, - '50-59': 267150, - '60-69': 151072, - '70-79': 67185, - '80+': 18553}, - 'Mauritius': {'0-9': 132887, - '10-19': 175164, - '20-29': 196809, - '30-39': 175108, - '40-49': 182089, - '50-59': 175349, - '60-69': 137990, - '70-79': 69212, - '80+': 27160}, - 'Mayotte': {'0-9': 71475, - '10-19': 64566, - '20-29': 43626, - '30-39': 32985, - '40-49': 27349, - '50-59': 16167, - '60-69': 9373, - '70-79': 4999, - '80+': 2275}, - 'Mexico': {'0-9': 22169248, - '10-19': 22350465, - '20-29': 21735593, - '30-39': 18880028, - '40-49': 16547760, - '50-59': 12757973, - '60-69': 8264954, - '70-79': 4188714, - '80+': 2038018}, - 'Micronesia (Federated States of)': {'0-9': 24050, - '10-19': 23299, - '20-29': 22347, - '30-39': 15087, - '40-49': 11429, - '50-59': 9786, - '60-69': 6733, - '70-79': 1930, - '80+': 362}, - 'Mongolia': {'0-9': 737476, - '10-19': 500441, - '20-29': 500018, - '30-39': 564279, - '40-49': 423046, - '50-59': 314050, - '60-69': 158364, - '70-79': 59891, - '80+': 20725}, - 'Montenegro': {'0-9': 73945, - '10-19': 78536, - '20-29': 84197, - '30-39': 88348, - '40-49': 83921, - '50-59': 80322, - '60-69': 76947, - '70-79': 40438, - '80+': 21412}, - 'Morocco': {'0-9': 6752613, - '10-19': 6097197, - '20-29': 5883282, - '30-39': 5606357, - '40-49': 4452433, - '50-59': 3743784, - '60-69': 2735019, - '70-79': 1197076, - '80+': 442799}, - 'Mozambique': {'0-9': 9717781, - '10-19': 7595457, - '20-29': 5294496, - '30-39': 3588739, - '40-49': 2289290, - '50-59': 1400167, - '60-69': 843662, - '70-79': 420844, - '80+': 104999}, - 'Myanmar': {'0-9': 9021262, - '10-19': 9916644, - '20-29': 9163079, - '30-39': 8073003, - '40-49': 7219972, - '50-59': 5573219, - '60-69': 3603964, - '70-79': 1423032, - '80+': 415625}, - 'Namibia': {'0-9': 654524, - '10-19': 526434, - '20-29': 472709, - '30-39': 356845, - '40-49': 237555, - '50-59': 150335, - '60-69': 87459, - '70-79': 41131, - '80+': 13913}, - 'Nepal': {'0-9': 5462982, - '10-19': 6120130, - '20-29': 5886374, - '30-39': 3792740, - '40-49': 3045655, - '50-59': 2307701, - '60-69': 1488078, - '70-79': 811531, - '80+': 221617}, - 'Netherlands': {'0-9': 1752759, - '10-19': 1953692, - '20-29': 2097478, - '30-39': 2097533, - '40-49': 2151439, - '50-59': 2524073, - '60-69': 2129499, - '70-79': 1591523, - '80+': 836876}, - 'New Caledonia': {'0-9': 41312, - '10-19': 43203, - '20-29': 43195, - '30-39': 41492, - '40-49': 40824, - '50-59': 34952, - '60-69': 22796, - '70-79': 13302, - '80+': 4422}, - 'New Zealand': {'0-9': 615286, - '10-19': 624953, - '20-29': 671233, - '30-39': 619065, - '40-49': 591875, - '50-59': 628690, - '60-69': 522312, - '70-79': 361834, - '80+': 186985}, - 'Nicaragua': {'0-9': 1317147, - '10-19': 1240161, - '20-29': 1165998, - '30-39': 1055451, - '40-49': 763037, - '50-59': 507320, - '60-69': 348753, - '70-79': 150503, - '80+': 76184}, - 'Niger': {'0-9': 8758024, - '10-19': 5901126, - '20-29': 3717358, - '30-39': 2259019, - '40-49': 1528697, - '50-59': 1046847, - '60-69': 644750, - '70-79': 295959, - '80+': 54863}, - 'Nigeria': {'0-9': 63852440, - '10-19': 47703190, - '20-29': 33177419, - '30-39': 24368050, - '40-49': 17037463, - '50-59': 10700169, - '60-69': 6258527, - '70-79': 2623704, - '80+': 418627}, - 'Norway': {'0-9': 614323, - '10-19': 643032, - '20-29': 726383, - '30-39': 738722, - '40-49': 724932, - '50-59': 712508, - '60-69': 586156, - '70-79': 446446, - '80+': 228739}, - 'Oman': {'0-9': 832571, - '10-19': 530302, - '20-29': 1085546, - '30-39': 1439821, - '40-49': 684970, - '50-59': 315603, - '60-69': 142788, - '70-79': 53058, - '80+': 21967}, - 'Pakistan': {'0-9': 53462231, - '10-19': 45427436, - '20-29': 39930365, - '30-39': 30816025, - '40-49': 21248749, - '50-59': 15122610, - '60-69': 8902414, - '70-79': 4558931, - '80+': 1423578}, - 'Panama': {'0-9': 773776, - '10-19': 726611, - '20-29': 678255, - '30-39': 618598, - '40-49': 556394, - '50-59': 432978, - '60-69': 282630, - '70-79': 157808, - '80+': 87717}, - 'Papua New Guinea': {'0-9': 2150349, - '10-19': 1917879, - '20-29': 1554186, - '30-39': 1220537, - '40-49': 938383, - '50-59': 629120, - '60-69': 372086, - '70-79': 136653, - '80+': 27831}, - 'Paraguay': {'0-9': 1383914, - '10-19': 1336278, - '20-29': 1321044, - '30-39': 1109127, - '40-49': 727641, - '50-59': 548361, - '60-69': 402162, - '70-79': 213726, - '80+': 90284}, - 'Peru': {'0-9': 5445401, - '10-19': 5134606, - '20-29': 5375787, - '30-39': 5231161, - '40-49': 4346665, - '50-59': 3313880, - '60-69': 2276639, - '70-79': 1255406, - '80+': 592307}, - 'Philippines': {'0-9': 22014291, - '10-19': 21369694, - '20-29': 19584112, - '30-39': 15501925, - '40-49': 12311228, - '50-59': 9366918, - '60-69': 5878871, - '70-79': 2639622, - '80+': 914417}, - 'Poland': {'0-9': 3784870, - '10-19': 3709138, - '20-29': 4431561, - '30-39': 6004923, - '40-49': 5535441, - '50-59': 4563170, - '60-69': 5174147, - '70-79': 2900526, - '80+': 1742835}, - 'Portugal': {'0-9': 841075, - '10-19': 1015167, - '20-29': 1073698, - '30-39': 1215310, - '40-49': 1575910, - '50-59': 1481008, - '60-69': 1293823, - '70-79': 1018315, - '80+': 682403}, - 'Puerto Rico': {'0-9': 240324, - '10-19': 394671, - '20-29': 288754, - '30-39': 331516, - '40-49': 399245, - '50-59': 414187, - '60-69': 361026, - '70-79': 273683, - '80+': 157447}, - 'Qatar': {'0-9': 270534, - '10-19': 228399, - '20-29': 717369, - '30-39': 846180, - '40-49': 461797, - '50-59': 254159, - '60-69': 81798, - '70-79': 16725, - '80+': 4092}, - 'Republic of Korea': {'0-9': 4153813, - '10-19': 4753259, - '20-29': 6716295, - '30-39': 7079840, - '40-49': 8218845, - '50-59': 8476698, - '60-69': 6453706, - '70-79': 3560645, - '80+': 1856084}, - 'Republic of Moldova': {'0-9': 424059, - '10-19': 419285, - '20-29': 570832, - '30-39': 773875, - '40-49': 562809, - '50-59': 521014, - '60-69': 488289, - '70-79': 184990, - '80+': 88810}, - 'Romania': {'0-9': 1905045, - '10-19': 2075305, - '20-29': 2086267, - '30-39': 2585899, - '40-49': 3026469, - '50-59': 2569160, - '60-69': 2535949, - '70-79': 1530270, - '80+': 923327}, - 'Russian Federation': {'0-9': 18622607, - '10-19': 15256035, - '20-29': 15607785, - '30-39': 24468554, - '40-49': 20375320, - '50-59': 18897667, - '60-69': 18501370, - '70-79': 8549716, - '80+': 5655408}, - 'Rwanda': {'0-9': 3561022, - '10-19': 2905796, - '20-29': 2211046, - '30-39': 1812553, - '40-49': 1070096, - '50-59': 728451, - '60-69': 445152, - '70-79': 174816, - '80+': 43285}, - 'Réunion': {'0-9': 132395, - '10-19': 138862, - '20-29': 118273, - '30-39': 99451, - '40-49': 117324, - '50-59': 125415, - '60-69': 90557, - '70-79': 47535, - '80+': 25500}, - 'Saint Lucia': {'0-9': 21813, - '10-19': 24336, - '20-29': 32816, - '30-39': 28448, - '40-49': 25516, - '50-59': 23375, - '60-69': 14556, - '70-79': 8355, - '80+': 4412}, - 'Saint Vincent and the Grenadines': {'0-9': 15945, - '10-19': 17425, - '20-29': 17503, - '30-39': 15712, - '40-49': 14485, - '50-59': 13587, - '60-69': 9176, - '70-79': 4503, - '80+': 2604}, - 'Samoa': {'0-9': 51121, - '10-19': 42003, - '20-29': 31297, - '30-39': 22010, - '40-49': 19559, - '50-59': 16472, - '60-69': 9961, - '70-79': 4578, - '80+': 1413}, - 'Sao Tome and Principe': {'0-9': 62410, - '10-19': 54109, - '20-29': 33623, - '30-39': 26630, - '40-49': 18680, - '50-59': 12781, - '60-69': 7083, - '70-79': 2763, - '80+': 1080}, - 'Saudi Arabia': {'0-9': 5956215, - '10-19': 4860281, - '20-29': 5354763, - '30-39': 6980363, - '40-49': 6408790, - '50-59': 3216573, - '60-69': 1373521, - '70-79': 493856, - '80+': 169509}, - 'Senegal': {'0-9': 5032581, - '10-19': 3863701, - '20-29': 2823536, - '30-39': 2051292, - '40-49': 1331829, - '50-59': 834697, - '60-69': 505761, - '70-79': 239181, - '80+': 61349}, - 'Serbia': {'0-9': 855818, - '10-19': 999733, - '20-29': 1102466, - '30-39': 1214888, - '40-49': 1229894, - '50-59': 1121507, - '60-69': 1142469, - '70-79': 729682, - '80+': 340914}, - 'Seychelles': {'0-9': 15935, - '10-19': 13867, - '20-29': 13431, - '30-39': 14488, - '40-49': 14873, - '50-59': 12978, - '60-69': 7911, - '70-79': 3205, - '80+': 1659}, - 'Sierra Leone': {'0-9': 2225885, - '10-19': 1867195, - '20-29': 1405514, - '30-39': 1017051, - '40-49': 672892, - '50-59': 419133, - '60-69': 234027, - '70-79': 108809, - '80+': 26477}, - 'Singapore': {'0-9': 479039, - '10-19': 505791, - '20-29': 833056, - '30-39': 896616, - '40-49': 964875, - '50-59': 946223, - '60-69': 799325, - '70-79': 289630, - '80+': 135787}, - 'Slovakia': {'0-9': 566590, - '10-19': 545493, - '20-29': 655787, - '30-39': 847604, - '40-49': 861400, - '50-59': 709218, - '60-69': 695209, - '70-79': 398709, - '80+': 179632}, - 'Slovenia': {'0-9': 210171, - '10-19': 196378, - '20-29': 205492, - '30-39': 283648, - '40-49': 305327, - '50-59': 301204, - '60-69': 284942, - '70-79': 177497, - '80+': 114279}, - 'Solomon Islands': {'0-9': 196169, - '10-19': 148827, - '20-29': 111830, - '30-39': 82051, - '40-49': 68670, - '50-59': 40695, - '60-69': 22979, - '70-79': 11993, - '80+': 3670}, - 'Somalia': {'0-9': 5215365, - '10-19': 3937588, - '20-29': 2693878, - '30-39': 1534402, - '40-49': 1053897, - '50-59': 733973, - '60-69': 462792, - '70-79': 210106, - '80+': 51221}, - 'South Africa': {'0-9': 11585606, - '10-19': 10409174, - '20-29': 10141490, - '30-39': 10155325, - '40-49': 7043274, - '50-59': 4911530, - '60-69': 3164440, - '70-79': 1476055, - '80+': 421796}, - 'South Sudan': {'0-9': 3245684, - '10-19': 2581903, - '20-29': 1962948, - '30-39': 1334152, - '40-49': 896838, - '50-59': 595522, - '60-69': 344938, - '70-79': 182625, - '80+': 49115}, - 'Spain': {'0-9': 4234486, - '10-19': 4736076, - '20-29': 4617599, - '30-39': 5901992, - '40-49': 7938499, - '50-59': 7046327, - '60-69': 5340654, - '70-79': 4015304, - '80+': 2923841}, - 'Sri Lanka': {'0-9': 3350035, - '10-19': 3386220, - '20-29': 2901858, - '30-39': 2820020, - '40-49': 2881105, - '50-59': 2554817, - '60-69': 2013196, - '70-79': 1146337, - '80+': 359661}, - 'State of Palestine': {'0-9': 1364529, - '10-19': 1109494, - '20-29': 965726, - '30-39': 664295, - '40-49': 448138, - '50-59': 297319, - '60-69': 151853, - '70-79': 77833, - '80+': 22227}, - 'Sudan': {'0-9': 12128803, - '10-19': 10123658, - '20-29': 7627155, - '30-39': 5203245, - '40-49': 3727317, - '50-59': 2552951, - '60-69': 1535958, - '70-79': 733051, - '80+': 217121}, - 'Suriname': {'0-9': 104833, - '10-19': 102229, - '20-29': 95774, - '30-39': 82789, - '40-49': 72724, - '50-59': 64826, - '60-69': 36928, - '70-79': 18682, - '80+': 7847}, - 'Sweden': {'0-9': 1193952, - '10-19': 1127126, - '20-29': 1276929, - '30-39': 1320296, - '40-49': 1264123, - '50-59': 1296645, - '60-69': 1093869, - '70-79': 994243, - '80+': 532082}, - 'Switzerland': {'0-9': 884945, - '10-19': 834866, - '20-29': 1039727, - '30-39': 1219227, - '40-49': 1166590, - '50-59': 1320623, - '60-69': 977436, - '70-79': 751994, - '80+': 459214}, - 'Syrian Arab Republic': {'0-9': 3635906, - '10-19': 3325125, - '20-29': 3099981, - '30-39': 2907195, - '40-49': 1928900, - '50-59': 1285347, - '60-69': 822366, - '70-79': 355547, - '80+': 140291}, - 'Taiwan Province of China': {'0-9': 2052885, - '10-19': 2188808, - '20-29': 3120353, - '30-39': 3548586, - '40-49': 3787845, - '50-59': 3659220, - '60-69': 3101016, - '70-79': 1488802, - '80+': 869260}, - 'Tajikistan': {'0-9': 2577608, - '10-19': 1788370, - '20-29': 1648520, - '30-39': 1390332, - '40-49': 882400, - '50-59': 700892, - '60-69': 387890, - '70-79': 117606, - '80+': 44027}, - 'Thailand': {'0-9': 7439833, - '10-19': 8492312, - '20-29': 9630311, - '30-39': 9229726, - '40-49': 10914254, - '50-59': 10681391, - '60-69': 7624358, - '70-79': 3866567, - '80+': 1921226}, - 'The former Yugoslav Republic of Macedonia': {'0-9': 227550, - '10-19': 233451, - '20-29': 282982, - '30-39': 325975, - '40-49': 299904, - '50-59': 282831, - '60-69': 244647, - '70-79': 133880, - '80+': 52154}, - 'Timor-Leste': {'0-9': 331877, - '10-19': 306717, - '20-29': 244908, - '30-39': 159027, - '40-49': 100789, - '50-59': 88473, - '60-69': 50144, - '70-79': 28916, - '80+': 7594}, - 'Togo': {'0-9': 2340180, - '10-19': 1914993, - '20-29': 1375262, - '30-39': 1064553, - '40-49': 744517, - '50-59': 450710, - '60-69': 255935, - '70-79': 111491, - '80+': 21083}, - 'Tonga': {'0-9': 24640, - '10-19': 23525, - '20-29': 17138, - '30-39': 12181, - '40-49': 10289, - '50-59': 8701, - '60-69': 5304, - '70-79': 2791, - '80+': 1126}, - 'Trinidad and Tobago': {'0-9': 184450, - '10-19': 185807, - '20-29': 183001, - '30-39': 242864, - '40-49': 191443, - '50-59': 175059, - '60-69': 135895, - '70-79': 73653, - '80+': 27316}, - 'Tunisia': {'0-9': 2017758, - '10-19': 1639937, - '20-29': 1725345, - '30-39': 1914066, - '40-49': 1572474, - '50-59': 1361507, - '60-69': 962594, - '70-79': 424105, - '80+': 200832}, - 'Turkey': {'0-9': 13419270, - '10-19': 13595150, - '20-29': 13174164, - '30-39': 12774732, - '40-49': 11446581, - '50-59': 8908423, - '60-69': 6192391, - '70-79': 3353577, - '80+': 1474778}, - 'Turkmenistan': {'0-9': 1332932, - '10-19': 1008742, - '20-29': 1009792, - '30-39': 957887, - '40-49': 697821, - '50-59': 535461, - '60-69': 334447, - '70-79': 103460, - '80+': 50658}, - 'Uganda': {'0-9': 14855951, - '10-19': 11449426, - '20-29': 7872675, - '30-39': 5101102, - '40-49': 3133402, - '50-59': 1852437, - '60-69': 974327, - '70-79': 411999, - '80+': 89688}, - 'Ukraine': {'0-9': 4589511, - '10-19': 4383518, - '20-29': 4898491, - '30-39': 7208959, - '40-49': 6406401, - '50-59': 5906740, - '60-69': 5539857, - '70-79': 2983432, - '80+': 1816853}, - 'United Arab Emirates': {'0-9': 1011712, - '10-19': 842993, - '20-29': 2149345, - '30-39': 3169316, - '40-49': 1608106, - '50-59': 797911, - '60-69': 242705, - '70-79': 55883, - '80+': 12431}, - 'United Kingdom of Great Britain and Northern Ireland': {'0-9': 8044056, - '10-19': 7642475, - '20-29': 8558707, - '30-39': 9295025, - '40-49': 8604251, - '50-59': 9173467, - '60-69': 7286778, - '70-79': 5830636, - '80+': 3450616}, - 'United Republic of Tanzania': {'0-9': 18362315, - '10-19': 14089046, - '20-29': 9846249, - '30-39': 7161926, - '40-49': 4820729, - '50-59': 2926636, - '60-69': 1622801, - '70-79': 741234, - '80+': 163282}, - 'United States Virgin Islands': {'0-9': 12866, - '10-19': 14018, - '20-29': 12732, - '30-39': 9733, - '40-49': 11766, - '50-59': 14450, - '60-69': 14020, - '70-79': 10901, - '80+': 3939}, - 'United States of America': {'0-9': 39721484, - '10-19': 42332393, - '20-29': 46094077, - '30-39': 44668271, - '40-49': 40348398, - '50-59': 42120077, - '60-69': 38488173, - '70-79': 24082598, - '80+': 13147180}, - 'Uruguay': {'0-9': 473071, - '10-19': 478929, - '20-29': 511559, - '30-39': 461146, - '40-49': 455021, - '50-59': 391074, - '60-69': 327921, - '70-79': 220267, - '80+': 154741}, - 'Uzbekistan': {'0-9': 6713724, - '10-19': 5460857, - '20-29': 5946988, - '30-39': 5577195, - '40-49': 3930502, - '50-59': 3068759, - '60-69': 1939630, - '70-79': 572151, - '80+': 259397}, - 'Vanuatu': {'0-9': 80884, - '10-19': 66925, - '20-29': 50769, - '30-39': 41001, - '40-49': 29192, - '50-59': 20541, - '60-69': 11438, - '70-79': 4837, - '80+': 1558}, - 'Venezuela (Bolivarian Republic of)': {'0-9': 5094601, - '10-19': 5158570, - '20-29': 4130338, - '30-39': 4027919, - '40-49': 3564976, - '50-59': 3014982, - '60-69': 2042554, - '70-79': 989858, - '80+': 412141}, - 'Viet Nam': {'0-9': 15478572, - '10-19': 13599041, - '20-29': 15389495, - '30-39': 16200926, - '40-49': 13572964, - '50-59': 11109965, - '60-69': 7342685, - '70-79': 2778470, - '80+': 1866461}, - 'Western Sahara': {'0-9': 112592, - '10-19': 98369, - '20-29': 104987, - '30-39': 108717, - '40-49': 82796, - '50-59': 51955, - '60-69': 28373, - '70-79': 7614, - '80+': 1936}, - 'Yemen': {'0-9': 8033406, - '10-19': 6750274, - '20-29': 5732747, - '30-39': 4140438, - '40-49': 2362805, - '50-59': 1422834, - '60-69': 879448, - '70-79': 403471, - '80+': 100540}, - 'Zambia': {'0-9': 5663541, - '10-19': 4550182, - '20-29': 3180383, - '30-39': 2185196, - '40-49': 1413887, - '50-59': 761262, - '60-69': 403835, - '70-79': 179963, - '80+': 45706}, - 'Zimbabwe': {'0-9': 4308157, - '10-19': 3559952, - '20-29': 2482990, - '30-39': 1867477, - '40-49': 1257821, - '50-59': 698090, - '60-69': 425415, - '70-79': 200359, - '80+': 62663} - } - return output \ No newline at end of file +expressed as a Python file. +''' + +data = { + 'Afghanistan': {'0-9': 11088731, + '10-19': 9821561, + '20-29': 7035871, + '30-39': 4534646, + '40-49': 2963460, + '50-59': 1840199, + '60-69': 1057497, + '70-79': 480455, + '80+': 105925}, + 'Albania': {'0-9': 333832, + '10-19': 361777, + '20-29': 472678, + '30-39': 390771, + '40-49': 323020, + '50-59': 386091, + '60-69': 330244, + '70-79': 194668, + '80+': 84716}, + 'Algeria': {'0-9': 9677492, + '10-19': 6731745, + '20-29': 6573711, + '30-39': 7275234, + '40-49': 5448620, + '50-59': 3800054, + '60-69': 2530543, + '70-79': 1237832, + '80+': 575811}, + 'Angola': {'0-9': 10899167, + '10-19': 7881777, + '20-29': 5306039, + '30-39': 3699729, + '40-49': 2412736, + '50-59': 1464604, + '60-69': 785896, + '70-79': 331730, + '80+': 84594}, + 'Antigua and Barbuda': {'0-9': 14582, + '10-19': 13868, + '20-29': 14895, + '30-39': 14095, + '40-49': 13860, + '50-59': 12832, + '60-69': 8042, + '70-79': 4101, + '80+': 1654}, + 'Argentina': {'0-9': 7446465, + '10-19': 7136712, + '20-29': 6997584, + '30-39': 6441412, + '40-49': 5727746, + '50-59': 4424939, + '60-69': 3528743, + '70-79': 2300637, + '80+': 1191536}, + 'Armenia': {'0-9': 418860, + '10-19': 368930, + '20-29': 408926, + '30-39': 503954, + '40-49': 353090, + '50-59': 362654, + '60-69': 328401, + '70-79': 126744, + '80+': 91684}, + 'Aruba': {'0-9': 11758, + '10-19': 14010, + '20-29': 14980, + '30-39': 11241, + '40-49': 14271, + '50-59': 17207, + '60-69': 13753, + '70-79': 6956, + '80+': 2590}, + 'Australia': {'0-9': 3308972, + '10-19': 3130480, + '20-29': 3375453, + '30-39': 3718346, + '40-49': 3306061, + '50-59': 3107734, + '60-69': 2651187, + '70-79': 1846377, + '80+': 1055274}, + 'Austria': {'0-9': 874182, + '10-19': 876207, + '20-29': 1115378, + '30-39': 1243414, + '40-49': 1178265, + '50-59': 1407001, + '60-69': 1033318, + '70-79': 790436, + '80+': 488197}, + 'Azerbaijan': {'0-9': 1686038, + '10-19': 1335455, + '20-29': 1608982, + '30-39': 1766690, + '40-49': 1280804, + '50-59': 1281076, + '60-69': 804312, + '70-79': 242762, + '80+': 133058}, + 'Bahamas': {'0-9': 53654, + '10-19': 63795, + '20-29': 66571, + '30-39': 55456, + '40-49': 56498, + '50-59': 49219, + '60-69': 29427, + '70-79': 13644, + '80+': 4980}, + 'Bahrain': {'0-9': 218134, + '10-19': 181855, + '20-29': 306667, + '30-39': 507735, + '40-49': 256720, + '50-59': 140231, + '60-69': 66573, + '70-79': 17815, + '80+': 5845}, + 'Bangladesh': {'0-9': 28972611, + '10-19': 30674421, + '20-29': 29765032, + '30-39': 26511633, + '40-49': 20651269, + '50-59': 15005706, + '60-69': 7296839, + '70-79': 4095813, + '80+': 1716059}, + 'Barbados': {'0-9': 30617, + '10-19': 36514, + '20-29': 37578, + '30-39': 37124, + '40-49': 39068, + '50-59': 39936, + '60-69': 33573, + '70-79': 20154, + '80+': 12811}, + 'Belarus': {'0-9': 1143840, + '10-19': 928884, + '20-29': 1077804, + '30-39': 1530347, + '40-49': 1285399, + '50-59': 1345792, + '60-69': 1243251, + '70-79': 525562, + '80+': 368444}, + 'Belgium': {'0-9': 1302703, + '10-19': 1312253, + '20-29': 1386087, + '30-39': 1504000, + '40-49': 1518439, + '50-59': 1598741, + '60-69': 1369875, + '70-79': 939415, + '80+': 658110}, + 'Belize': {'0-9': 78107, + '10-19': 77850, + '20-29': 75822, + '30-39': 59711, + '40-49': 43959, + '50-59': 31811, + '60-69': 17817, + '70-79': 8310, + '80+': 4240}, + 'Benin': {'0-9': 3596952, + '10-19': 2779488, + '20-29': 2061769, + '30-39': 1436440, + '40-49': 981831, + '50-59': 650680, + '60-69': 379184, + '70-79': 184835, + '80+': 52021}, + 'Bhutan': {'0-9': 125825, + '10-19': 135992, + '20-29': 153315, + '30-39': 138679, + '40-49': 89605, + '50-59': 59011, + '60-69': 36910, + '70-79': 22235, + '80+': 10036}, + 'Bolivia (Plurinational State of)': {'0-9': 2364587, + '10-19': 2297693, + '20-29': 2039536, + '30-39': 1639098, + '40-49': 1238341, + '50-59': 883592, + '60-69': 615318, + '70-79': 391940, + '80+': 202916}, + 'Bosnia and Herzegovina': {'0-9': 295215, + '10-19': 346276, + '20-29': 403273, + '30-39': 458386, + '40-49': 447738, + '50-59': 500181, + '60-69': 463795, + '70-79': 242499, + '80+': 123456}, + 'Botswana': {'0-9': 539004, + '10-19': 472033, + '20-29': 402508, + '30-39': 365289, + '40-49': 261017, + '50-59': 146580, + '60-69': 104252, + '70-79': 48560, + '80+': 12384}, + 'Brazil': {'0-9': 29076912, + '10-19': 31160447, + '20-29': 34104644, + '30-39': 34476764, + '40-49': 29462008, + '50-59': 24421199, + '60-69': 16896864, + '70-79': 8801551, + '80+': 4159028}, + 'Brunei Darussalam': {'0-9': 66355, + '10-19': 65082, + '20-29': 69697, + '30-39': 76569, + '40-49': 68004, + '50-59': 50218, + '60-69': 28512, + '70-79': 9570, + '80+': 3471}, + 'Bulgaria': {'0-9': 649382, + '10-19': 685881, + '20-29': 689917, + '30-39': 957591, + '40-49': 1061986, + '50-59': 944703, + '60-69': 922593, + '70-79': 710368, + '80+': 326024}, + 'Burkina Faso': {'0-9': 6552186, + '10-19': 5029543, + '20-29': 3508067, + '30-39': 2428031, + '40-49': 1587132, + '50-59': 977489, + '60-69': 538877, + '70-79': 234236, + '80+': 47712}, + 'Burundi': {'0-9': 3872449, + '10-19': 2725292, + '20-29': 2029583, + '30-39': 1539545, + '40-49': 747634, + '50-59': 491973, + '60-69': 339630, + '70-79': 112127, + '80+': 32551}, + 'Cabo Verde': {'0-9': 105077, + '10-19': 99937, + '20-29': 97847, + '30-39': 98288, + '40-49': 64905, + '50-59': 47913, + '60-69': 26368, + '70-79': 9054, + '80+': 6598}, + 'Cambodia': {'0-9': 3530588, + '10-19': 3100069, + '20-29': 3117605, + '30-39': 2889268, + '40-49': 1429088, + '50-59': 1387484, + '60-69': 816774, + '70-79': 352443, + '80+': 95646}, + 'Cameroon': {'0-9': 7846025, + '10-19': 6176460, + '20-29': 4551789, + '30-39': 3399844, + '40-49': 2141843, + '50-59': 1288476, + '60-69': 733298, + '70-79': 332733, + '80+': 75395}, + 'Canada': {'0-9': 3970918, + '10-19': 3971318, + '20-29': 5096615, + '30-39': 5278663, + '40-49': 4846667, + '50-59': 5182430, + '60-69': 4712746, + '70-79': 3018677, + '80+': 1664120}, + 'Central African Republic': {'0-9': 1435610, + '10-19': 1264610, + '20-29': 839989, + '30-39': 501334, + '40-49': 339531, + '50-59': 232597, + '60-69': 139061, + '70-79': 61505, + '80+': 15530}, + 'Chad': {'0-9': 5452555, + '10-19': 4038729, + '20-29': 2781016, + '30-39': 1769644, + '40-49': 1082834, + '50-59': 654647, + '60-69': 417351, + '70-79': 180661, + '80+': 48427}, + 'Channel Islands': {'0-9': 17565, + '10-19': 17778, + '20-29': 21767, + '30-39': 23888, + '40-49': 24915, + '50-59': 26180, + '60-69': 20014, + '70-79': 13295, + '80+': 8461}, + 'Chile': {'0-9': 2428078, + '10-19': 2493875, + '20-29': 2995538, + '30-39': 2945403, + '40-49': 2578406, + '50-59': 2352271, + '60-69': 1791785, + '70-79': 993127, + '80+': 537718}, + 'China': {'0-9': 170667621, + '10-19': 166604608, + '20-29': 185147173, + '30-39': 228830425, + '40-49': 216111764, + '50-59': 222185873, + '60-69': 151663904, + '70-79': 71494306, + '80+': 26618102}, + 'China, Hong Kong Special Administrative Region': {'0-9': 664195, + '10-19': 552658, + '20-29': 867629, + '30-39': 1122165, + '40-49': 1129131, + '50-59': 1207906, + '60-69': 1048879, + '70-79': 525082, + '80+': 379336}, + 'China, Macao Special Administrative Region': {'0-9': 68816, + '10-19': 46834, + '20-29': 88333, + '30-39': 129800, + '40-49': 93400, + '50-59': 99614, + '60-69': 78993, + '70-79': 29881, + '80+': 13664}, + 'Colombia': {'0-9': 7414157, + '10-19': 8119877, + '20-29': 8847062, + '30-39': 7810299, + '40-49': 6450787, + '50-59': 5543982, + '60-69': 3771360, + '70-79': 1979762, + '80+': 945605}, + 'Comoros': {'0-9': 237638, + '10-19': 191272, + '20-29': 150847, + '30-39': 117375, + '40-49': 77037, + '50-59': 50890, + '60-69': 29657, + '70-79': 11660, + '80+': 3225}, + 'Congo': {'0-9': 1592333, + '10-19': 1257962, + '20-29': 874259, + '30-39': 680079, + '40-49': 535815, + '50-59': 327893, + '60-69': 164736, + '70-79': 69397, + '80+': 15613}, + 'Costa Rica': {'0-9': 705597, + '10-19': 718839, + '20-29': 824456, + '30-39': 825655, + '40-49': 650563, + '50-59': 602394, + '60-69': 423012, + '70-79': 230865, + '80+': 112737}, + 'Croatia': {'0-9': 385776, + '10-19': 408108, + '20-29': 472201, + '30-39': 539290, + '40-49': 557001, + '50-59': 581382, + '60-69': 565376, + '70-79': 361956, + '80+': 234177}, + 'Cuba': {'0-9': 1199375, + '10-19': 1246736, + '20-29': 1421019, + '30-39': 1523032, + '40-49': 1561981, + '50-59': 1967294, + '60-69': 1174022, + '70-79': 804207, + '80+': 428950}, + 'Curaçao': {'0-9': 19332, + '10-19': 21569, + '20-29': 19539, + '30-39': 18724, + '40-49': 20279, + '50-59': 24425, + '60-69': 20705, + '70-79': 13003, + '80+': 6517}, + 'Cyprus': {'0-9': 132391, + '10-19': 141658, + '20-29': 191801, + '30-39': 188388, + '40-49': 166627, + '50-59': 147538, + '60-69': 120401, + '70-79': 78681, + '80+': 39873}, + 'Czechia': {'0-9': 1113645, + '10-19': 1061333, + '20-29': 1105336, + '30-39': 1478211, + '40-49': 1798356, + '50-59': 1351269, + '60-69': 1324617, + '70-79': 1031099, + '80+': 445115}, + 'Côte d’Ivoire': {'0-9': 7750285, + '10-19': 6104859, + '20-29': 4660993, + '30-39': 3172218, + '40-49': 2117549, + '50-59': 1337227, + '60-69': 822065, + '70-79': 341744, + '80+': 71333}, + "Democratic People's Republic of Korea": {'0-9': 3430376, + '10-19': 3561227, + '20-29': 3925716, + '30-39': 3641896, + '40-49': 3714317, + '50-59': 3622786, + '60-69': 2134680, + '70-79': 1303957, + '80+': 443861}, + 'Democratic Republic of the Congo': {'0-9': 29487305, + '10-19': 21000019, + '20-29': 14169239, + '30-39': 9762333, + '40-49': 6605529, + '50-59': 4347003, + '60-69': 2585842, + '70-79': 1268687, + '80+': 335446}, + 'Denmark': {'0-9': 606028, + '10-19': 675946, + '20-29': 775962, + '30-39': 672290, + '40-49': 738209, + '50-59': 810126, + '60-69': 654530, + '70-79': 586139, + '80+': 272972}, + 'Djibouti': {'0-9': 197110, + '10-19': 179320, + '20-29': 177326, + '30-39': 162418, + '40-49': 120923, + '50-59': 78074, + '60-69': 44336, + '70-79': 22330, + '80+': 6163}, + 'Dominican Republic': {'0-9': 1999349, + '10-19': 1935877, + '20-29': 1854317, + '30-39': 1564383, + '40-49': 1274489, + '50-59': 1014335, + '60-69': 682138, + '70-79': 341500, + '80+': 181522}, + 'Ecuador': {'0-9': 3277730, + '10-19': 3115981, + '20-29': 3036186, + '30-39': 2592840, + '40-49': 2088240, + '50-59': 1591141, + '60-69': 1087740, + '70-79': 570125, + '80+': 283071}, + 'Egypt': {'0-9': 25028540, + '10-19': 18385431, + '20-29': 16511130, + '30-39': 15198348, + '40-49': 10948603, + '50-59': 7844894, + '60-69': 5122656, + '70-79': 2530981, + '80+': 763821}, + 'El Salvador': {'0-9': 1146823, + '10-19': 1165823, + '20-29': 1215815, + '30-39': 882443, + '40-49': 725144, + '50-59': 568072, + '60-69': 406296, + '70-79': 248393, + '80+': 127396}, + 'Equatorial Guinea': {'0-9': 371662, + '10-19': 265295, + '20-29': 286389, + '30-39': 248982, + '40-49': 115361, + '50-59': 62216, + '60-69': 34879, + '70-79': 14719, + '80+': 3482}, + 'Eritrea': {'0-9': 971768, + '10-19': 860627, + '20-29': 572233, + '30-39': 460764, + '40-49': 280838, + '50-59': 171949, + '60-69': 128327, + '70-79': 77079, + '80+': 22836}, + 'Estonia': {'0-9': 143661, + '10-19': 137487, + '20-29': 145554, + '30-39': 193631, + '40-49': 184936, + '50-59': 165282, + '60-69': 169473, + '70-79': 107430, + '80+': 79081}, + 'Eswatini': {'0-9': 286620, + '10-19': 277020, + '20-29': 212889, + '30-39': 161329, + '40-49': 104399, + '50-59': 51716, + '60-69': 36524, + '70-79': 22581, + '80+': 7086}, + 'Ethiopia': {'0-9': 32037548, + '10-19': 26828994, + '20-29': 21439043, + '30-39': 13792878, + '40-49': 9038652, + '50-59': 5704067, + '60-69': 3624557, + '70-79': 1929368, + '80+': 568479}, + 'Fiji': {'0-9': 177143, + '10-19': 158135, + '20-29': 141943, + '30-39': 134953, + '40-49': 106524, + '50-59': 91436, + '60-69': 57120, + '70-79': 23633, + '80+': 5558}, + 'Finland': {'0-9': 568681, + '10-19': 606659, + '20-29': 672353, + '30-39': 706581, + '40-49': 659560, + '50-59': 720555, + '60-69': 712327, + '70-79': 582988, + '80+': 311016}, + 'France': {'0-9': 7527473, + '10-19': 7883476, + '20-29': 7371030, + '30-39': 8011050, + '40-49': 8325670, + '50-59': 8635055, + '60-69': 7764785, + '70-79': 5727704, + '80+': 4027268}, + 'French Guiana': {'0-9': 66122, + '10-19': 57555, + '20-29': 46109, + '30-39': 38719, + '40-49': 36992, + '50-59': 26711, + '60-69': 17226, + '70-79': 7221, + '80+': 2027}, + 'French Polynesia': {'0-9': 39637, + '10-19': 44133, + '20-29': 40379, + '30-39': 43366, + '40-49': 39589, + '50-59': 35650, + '60-69': 23042, + '70-79': 10823, + '80+': 4289}, + 'Gabon': {'0-9': 600005, + '10-19': 422773, + '20-29': 367412, + '30-39': 350071, + '40-49': 232167, + '50-59': 134150, + '60-69': 71303, + '70-79': 36691, + '80+': 11162}, + 'Gambia': {'0-9': 762307, + '10-19': 556857, + '20-29': 429180, + '30-39': 283130, + '40-49': 174068, + '50-59': 115915, + '60-69': 59281, + '70-79': 30007, + '80+': 5923}, + 'Georgia': {'0-9': 553163, + '10-19': 471056, + '20-29': 500696, + '30-39': 565077, + '40-49': 517944, + '50-59': 523623, + '60-69': 459856, + '70-79': 248784, + '80+': 148968}, + 'Germany': {'0-9': 7880902, + '10-19': 7930616, + '20-29': 9377359, + '30-39': 10872019, + '40-49': 10243351, + '50-59': 13488393, + '60-69': 10644140, + '70-79': 7471414, + '80+': 5875748}, + 'Ghana': {'0-9': 8057871, + '10-19': 6616719, + '20-29': 5398591, + '30-39': 4190417, + '40-49': 3031249, + '50-59': 2134980, + '60-69': 1091069, + '70-79': 456786, + '80+': 95258}, + 'Greece': {'0-9': 881128, + '10-19': 1068855, + '20-29': 1057214, + '30-39': 1336517, + '40-49': 1574408, + '50-59': 1505692, + '60-69': 1257161, + '70-79': 956084, + '80+': 785994}, + 'Grenada': {'0-9': 18132, + '10-19': 16137, + '20-29': 18288, + '30-39': 18211, + '40-49': 12874, + '50-59': 12146, + '60-69': 9573, + '70-79': 4789, + '80+': 2373}, + 'Guadeloupe': {'0-9': 44992, + '10-19': 58514, + '20-29': 46875, + '30-39': 33762, + '40-49': 49307, + '50-59': 62202, + '60-69': 50569, + '70-79': 32942, + '80+': 20961}, + 'Guam': {'0-9': 26981, + '10-19': 27159, + '20-29': 27031, + '30-39': 21837, + '40-49': 19935, + '50-59': 20162, + '60-69': 14330, + '70-79': 7777, + '80+': 3563}, + 'Guatemala': {'0-9': 4047466, + '10-19': 3871605, + '20-29': 3413158, + '30-39': 2532063, + '40-49': 1701991, + '50-59': 1053821, + '60-69': 718853, + '70-79': 382505, + '80+': 194106}, + 'Guinea': {'0-9': 3965625, + '10-19': 3199454, + '20-29': 2365739, + '30-39': 1470866, + '40-49': 898439, + '50-59': 614523, + '60-69': 408149, + '70-79': 171250, + '80+': 38750}, + 'Guinea-Bissau': {'0-9': 582349, + '10-19': 450031, + '20-29': 342383, + '30-39': 254507, + '40-49': 156574, + '50-59': 92190, + '60-69': 60417, + '70-79': 24637, + '80+': 4913}, + 'Guyana': {'0-9': 147626, + '10-19': 145351, + '20-29': 145302, + '30-39': 93113, + '40-49': 90525, + '50-59': 79336, + '60-69': 51355, + '70-79': 22936, + '80+': 11008}, + 'Haiti': {'0-9': 2500777, + '10-19': 2346528, + '20-29': 2044459, + '30-39': 1731657, + '40-49': 1106487, + '50-59': 789624, + '60-69': 523931, + '70-79': 260217, + '80+': 98848}, + 'Honduras': {'0-9': 2005992, + '10-19': 2064637, + '20-29': 1905416, + '30-39': 1470935, + '40-49': 1047736, + '50-59': 680012, + '60-69': 420079, + '70-79': 205312, + '80+': 104488}, + 'Hungary': {'0-9': 908567, + '10-19': 969206, + '20-29': 1151691, + '30-39': 1257140, + '40-49': 1588213, + '50-59': 1201387, + '60-69': 1306434, + '70-79': 846578, + '80+': 431135}, + 'Iceland': {'0-9': 43070, + '10-19': 44710, + '20-29': 47796, + '30-39': 46869, + '40-49': 42966, + '50-59': 42112, + '60-69': 37536, + '70-79': 23413, + '80+': 12771}, + 'India': {'0-9': 234861633, + '10-19': 252201517, + '20-29': 239902073, + '30-39': 215636276, + '40-49': 169660176, + '50-59': 128132229, + '60-69': 87150813, + '70-79': 39175398, + '80+': 13284270}, + 'Indonesia': {'0-9': 47956444, + '10-19': 46303002, + '20-29': 43571426, + '30-39': 41166623, + '40-49': 37846723, + '50-59': 29155099, + '60-69': 17531210, + '70-79': 7574475, + '80+': 2418613}, + 'Iran (Islamic Republic of)': {'0-9': 14565855, + '10-19': 11747928, + '20-29': 12342906, + '30-39': 16739444, + '40-49': 11655616, + '50-59': 8295330, + '60-69': 5396906, + '70-79': 2354607, + '80+': 894357}, + 'Iraq': {'0-9': 10610228, + '10-19': 8710756, + '20-29': 7165589, + '30-39': 5403684, + '40-49': 3936617, + '50-59': 2341151, + '60-69': 1292393, + '70-79': 573718, + '80+': 188357}, + 'Ireland': {'0-9': 671943, + '10-19': 668746, + '20-29': 567336, + '30-39': 695926, + '40-49': 763226, + '50-59': 600934, + '60-69': 480783, + '70-79': 330663, + '80+': 158229}, + 'Israel': {'0-9': 1671094, + '10-19': 1405063, + '20-29': 1196974, + '30-39': 1122245, + '40-49': 1040178, + '50-59': 795495, + '60-69': 703645, + '70-79': 459660, + '80+': 261181}, + 'Italy': {'0-9': 4994996, + '10-19': 5733447, + '20-29': 6103437, + '30-39': 6998434, + '40-49': 9022004, + '50-59': 9567192, + '60-69': 7484860, + '70-79': 6028907, + '80+': 4528548}, + 'Jamaica': {'0-9': 464791, + '10-19': 466600, + '20-29': 515497, + '30-39': 443384, + '40-49': 357431, + '50-59': 320532, + '60-69': 214542, + '70-79': 119523, + '80+': 58867}, + 'Japan': {'0-9': 10179968, + '10-19': 11267171, + '20-29': 12147325, + '30-39': 14455415, + '40-49': 18473078, + '50-59': 16541516, + '60-69': 15875236, + '70-79': 16185375, + '80+': 11351377}, + 'Jordan': {'0-9': 2212563, + '10-19': 2179854, + '20-29': 1802535, + '30-39': 1490607, + '40-49': 1141344, + '50-59': 755593, + '60-69': 366276, + '70-79': 190748, + '80+': 63614}, + 'Kazakhstan': {'0-9': 3868009, + '10-19': 2720923, + '20-29': 2573190, + '30-39': 2993496, + '40-49': 2286423, + '50-59': 2039442, + '60-69': 1438908, + '70-79': 552508, + '80+': 303808}, + 'Kenya': {'0-9': 14013908, + '10-19': 12746880, + '20-29': 9594275, + '30-39': 7470149, + '40-49': 4903045, + '50-59': 2805603, + '60-69': 1518824, + '70-79': 574335, + '80+': 144277}, + 'Kiribati': {'0-9': 29464, + '10-19': 23634, + '20-29': 20524, + '30-39': 16606, + '40-49': 11169, + '50-59': 9988, + '60-69': 5143, + '70-79': 2331, + '80+': 590}, + 'Kosovo': {'0-9': 294038, + '10-19': 306895, + '20-29': 299672, + '30-39': 237846, + '40-49': 228757, + '50-59': 189740, + '60-69': 127956, + '70-79': 71350, + '80+': 32684}, + 'Kuwait': {'0-9': 608328, + '10-19': 533225, + '20-29': 444882, + '30-39': 878557, + '40-49': 965368, + '50-59': 561299, + '60-69': 220263, + '70-79': 48552, + '80+': 10095}, + 'Kyrgyzstan': {'0-9': 1529449, + '10-19': 1100700, + '20-29': 1082940, + '30-39': 1014707, + '40-49': 686437, + '50-59': 581436, + '60-69': 363825, + '70-79': 111215, + '80+': 53484}, + "Lao People's Democratic Republic": {'0-9': 1566742, + '10-19': 1466251, + '20-29': 1362624, + '30-39': 1086530, + '40-49': 772683, + '50-59': 526580, + '60-69': 317973, + '70-79': 136165, + '80+': 40012}, + 'Latvia': {'0-9': 207770, + '10-19': 188723, + '20-29': 188221, + '30-39': 263219, + '40-49': 253889, + '50-59': 264241, + '60-69': 250143, + '70-79': 162705, + '80+': 107287}, + 'Lebanon': {'0-9': 1152160, + '10-19': 1134997, + '20-29': 1176573, + '30-39': 1009647, + '40-49': 862746, + '50-59': 724776, + '60-69': 447766, + '70-79': 211573, + '80+': 105207}, + 'Lesotho': {'0-9': 478747, + '10-19': 428822, + '20-29': 395193, + '30-39': 327280, + '40-49': 210253, + '50-59': 140769, + '60-69': 96810, + '70-79': 48309, + '80+': 16066}, + 'Liberia': {'0-9': 1418817, + '10-19': 1175027, + '20-29': 840855, + '30-39': 629808, + '40-49': 444196, + '50-59': 283827, + '60-69': 168470, + '70-79': 76455, + '80+': 20226}, + 'Libya': {'0-9': 1285422, + '10-19': 1185747, + '20-29': 1095417, + '30-39': 1163468, + '40-49': 1049198, + '50-59': 617153, + '60-69': 284261, + '70-79': 138926, + '80+': 51700}, + 'Lithuania': {'0-9': 300673, + '10-19': 242840, + '20-29': 316879, + '30-39': 337567, + '40-49': 355907, + '50-59': 420559, + '60-69': 352811, + '70-79': 223282, + '80+': 171771}, + 'Luxembourg': {'0-9': 65905, + '10-19': 65903, + '20-29': 85535, + '30-39': 98316, + '40-49': 94599, + '50-59': 90857, + '60-69': 62121, + '70-79': 37874, + '80+': 24867}, + 'Madagascar': {'0-9': 7762934, + '10-19': 6342928, + '20-29': 4898736, + '30-39': 3370908, + '40-49': 2387857, + '50-59': 1539765, + '60-69': 915207, + '70-79': 359863, + '80+': 112819}, + 'Malawi': {'0-9': 5662517, + '10-19': 4738054, + '20-29': 3377519, + '30-39': 2286024, + '40-49': 1436743, + '50-59': 846147, + '60-69': 480251, + '70-79': 244240, + '80+': 58457}, + 'Malaysia': {'0-9': 5143191, + '10-19': 5115769, + '20-29': 5770367, + '30-39': 5651218, + '40-49': 3990530, + '50-59': 3146037, + '60-69': 2151364, + '70-79': 1025182, + '80+': 372341}, + 'Maldives': {'0-9': 72820, + '10-19': 59438, + '20-29': 139684, + '30-39': 137607, + '40-49': 64647, + '50-59': 35317, + '60-69': 18164, + '70-79': 8467, + '80+': 4400}, + 'Mali': {'0-9': 6760318, + '10-19': 5009462, + '20-29': 3203821, + '30-39': 2160455, + '40-49': 1485960, + '50-59': 849115, + '60-69': 501293, + '70-79': 231083, + '80+': 49326}, + 'Malta': {'0-9': 43103, + '10-19': 40926, + '20-29': 55214, + '30-39': 65354, + '40-49': 59448, + '50-59': 53214, + '60-69': 57678, + '70-79': 45166, + '80+': 21440}, + 'Martinique': {'0-9': 35951, + '10-19': 47121, + '20-29': 41372, + '30-39': 34103, + '40-49': 44188, + '50-59': 62795, + '60-69': 52466, + '70-79': 33674, + '80+': 23595}, + 'Mauritania': {'0-9': 1307828, + '10-19': 1007554, + '20-29': 787903, + '30-39': 619780, + '40-49': 422633, + '50-59': 267150, + '60-69': 151072, + '70-79': 67185, + '80+': 18553}, + 'Mauritius': {'0-9': 132887, + '10-19': 175164, + '20-29': 196809, + '30-39': 175108, + '40-49': 182089, + '50-59': 175349, + '60-69': 137990, + '70-79': 69212, + '80+': 27160}, + 'Mayotte': {'0-9': 71475, + '10-19': 64566, + '20-29': 43626, + '30-39': 32985, + '40-49': 27349, + '50-59': 16167, + '60-69': 9373, + '70-79': 4999, + '80+': 2275}, + 'Mexico': {'0-9': 22169248, + '10-19': 22350465, + '20-29': 21735593, + '30-39': 18880028, + '40-49': 16547760, + '50-59': 12757973, + '60-69': 8264954, + '70-79': 4188714, + '80+': 2038018}, + 'Micronesia (Federated States of)': {'0-9': 24050, + '10-19': 23299, + '20-29': 22347, + '30-39': 15087, + '40-49': 11429, + '50-59': 9786, + '60-69': 6733, + '70-79': 1930, + '80+': 362}, + 'Mongolia': {'0-9': 737476, + '10-19': 500441, + '20-29': 500018, + '30-39': 564279, + '40-49': 423046, + '50-59': 314050, + '60-69': 158364, + '70-79': 59891, + '80+': 20725}, + 'Montenegro': {'0-9': 73945, + '10-19': 78536, + '20-29': 84197, + '30-39': 88348, + '40-49': 83921, + '50-59': 80322, + '60-69': 76947, + '70-79': 40438, + '80+': 21412}, + 'Morocco': {'0-9': 6752613, + '10-19': 6097197, + '20-29': 5883282, + '30-39': 5606357, + '40-49': 4452433, + '50-59': 3743784, + '60-69': 2735019, + '70-79': 1197076, + '80+': 442799}, + 'Mozambique': {'0-9': 9717781, + '10-19': 7595457, + '20-29': 5294496, + '30-39': 3588739, + '40-49': 2289290, + '50-59': 1400167, + '60-69': 843662, + '70-79': 420844, + '80+': 104999}, + 'Myanmar': {'0-9': 9021262, + '10-19': 9916644, + '20-29': 9163079, + '30-39': 8073003, + '40-49': 7219972, + '50-59': 5573219, + '60-69': 3603964, + '70-79': 1423032, + '80+': 415625}, + 'Namibia': {'0-9': 654524, + '10-19': 526434, + '20-29': 472709, + '30-39': 356845, + '40-49': 237555, + '50-59': 150335, + '60-69': 87459, + '70-79': 41131, + '80+': 13913}, + 'Nepal': {'0-9': 5462982, + '10-19': 6120130, + '20-29': 5886374, + '30-39': 3792740, + '40-49': 3045655, + '50-59': 2307701, + '60-69': 1488078, + '70-79': 811531, + '80+': 221617}, + 'Netherlands': {'0-9': 1752759, + '10-19': 1953692, + '20-29': 2097478, + '30-39': 2097533, + '40-49': 2151439, + '50-59': 2524073, + '60-69': 2129499, + '70-79': 1591523, + '80+': 836876}, + 'New Caledonia': {'0-9': 41312, + '10-19': 43203, + '20-29': 43195, + '30-39': 41492, + '40-49': 40824, + '50-59': 34952, + '60-69': 22796, + '70-79': 13302, + '80+': 4422}, + 'New Zealand': {'0-9': 615286, + '10-19': 624953, + '20-29': 671233, + '30-39': 619065, + '40-49': 591875, + '50-59': 628690, + '60-69': 522312, + '70-79': 361834, + '80+': 186985}, + 'Nicaragua': {'0-9': 1317147, + '10-19': 1240161, + '20-29': 1165998, + '30-39': 1055451, + '40-49': 763037, + '50-59': 507320, + '60-69': 348753, + '70-79': 150503, + '80+': 76184}, + 'Niger': {'0-9': 8758024, + '10-19': 5901126, + '20-29': 3717358, + '30-39': 2259019, + '40-49': 1528697, + '50-59': 1046847, + '60-69': 644750, + '70-79': 295959, + '80+': 54863}, + 'Nigeria': {'0-9': 63852440, + '10-19': 47703190, + '20-29': 33177419, + '30-39': 24368050, + '40-49': 17037463, + '50-59': 10700169, + '60-69': 6258527, + '70-79': 2623704, + '80+': 418627}, + 'Norway': {'0-9': 614323, + '10-19': 643032, + '20-29': 726383, + '30-39': 738722, + '40-49': 724932, + '50-59': 712508, + '60-69': 586156, + '70-79': 446446, + '80+': 228739}, + 'Oman': {'0-9': 832571, + '10-19': 530302, + '20-29': 1085546, + '30-39': 1439821, + '40-49': 684970, + '50-59': 315603, + '60-69': 142788, + '70-79': 53058, + '80+': 21967}, + 'Pakistan': {'0-9': 53462231, + '10-19': 45427436, + '20-29': 39930365, + '30-39': 30816025, + '40-49': 21248749, + '50-59': 15122610, + '60-69': 8902414, + '70-79': 4558931, + '80+': 1423578}, + 'Panama': {'0-9': 773776, + '10-19': 726611, + '20-29': 678255, + '30-39': 618598, + '40-49': 556394, + '50-59': 432978, + '60-69': 282630, + '70-79': 157808, + '80+': 87717}, + 'Papua New Guinea': {'0-9': 2150349, + '10-19': 1917879, + '20-29': 1554186, + '30-39': 1220537, + '40-49': 938383, + '50-59': 629120, + '60-69': 372086, + '70-79': 136653, + '80+': 27831}, + 'Paraguay': {'0-9': 1383914, + '10-19': 1336278, + '20-29': 1321044, + '30-39': 1109127, + '40-49': 727641, + '50-59': 548361, + '60-69': 402162, + '70-79': 213726, + '80+': 90284}, + 'Peru': {'0-9': 5445401, + '10-19': 5134606, + '20-29': 5375787, + '30-39': 5231161, + '40-49': 4346665, + '50-59': 3313880, + '60-69': 2276639, + '70-79': 1255406, + '80+': 592307}, + 'Philippines': {'0-9': 22014291, + '10-19': 21369694, + '20-29': 19584112, + '30-39': 15501925, + '40-49': 12311228, + '50-59': 9366918, + '60-69': 5878871, + '70-79': 2639622, + '80+': 914417}, + 'Poland': {'0-9': 3784870, + '10-19': 3709138, + '20-29': 4431561, + '30-39': 6004923, + '40-49': 5535441, + '50-59': 4563170, + '60-69': 5174147, + '70-79': 2900526, + '80+': 1742835}, + 'Portugal': {'0-9': 841075, + '10-19': 1015167, + '20-29': 1073698, + '30-39': 1215310, + '40-49': 1575910, + '50-59': 1481008, + '60-69': 1293823, + '70-79': 1018315, + '80+': 682403}, + 'Puerto Rico': {'0-9': 240324, + '10-19': 394671, + '20-29': 288754, + '30-39': 331516, + '40-49': 399245, + '50-59': 414187, + '60-69': 361026, + '70-79': 273683, + '80+': 157447}, + 'Qatar': {'0-9': 270534, + '10-19': 228399, + '20-29': 717369, + '30-39': 846180, + '40-49': 461797, + '50-59': 254159, + '60-69': 81798, + '70-79': 16725, + '80+': 4092}, + 'Republic of Korea': {'0-9': 4153813, + '10-19': 4753259, + '20-29': 6716295, + '30-39': 7079840, + '40-49': 8218845, + '50-59': 8476698, + '60-69': 6453706, + '70-79': 3560645, + '80+': 1856084}, + 'Republic of Moldova': {'0-9': 424059, + '10-19': 419285, + '20-29': 570832, + '30-39': 773875, + '40-49': 562809, + '50-59': 521014, + '60-69': 488289, + '70-79': 184990, + '80+': 88810}, + 'Romania': {'0-9': 1905045, + '10-19': 2075305, + '20-29': 2086267, + '30-39': 2585899, + '40-49': 3026469, + '50-59': 2569160, + '60-69': 2535949, + '70-79': 1530270, + '80+': 923327}, + 'Russian Federation': {'0-9': 18622607, + '10-19': 15256035, + '20-29': 15607785, + '30-39': 24468554, + '40-49': 20375320, + '50-59': 18897667, + '60-69': 18501370, + '70-79': 8549716, + '80+': 5655408}, + 'Rwanda': {'0-9': 3561022, + '10-19': 2905796, + '20-29': 2211046, + '30-39': 1812553, + '40-49': 1070096, + '50-59': 728451, + '60-69': 445152, + '70-79': 174816, + '80+': 43285}, + 'Réunion': {'0-9': 132395, + '10-19': 138862, + '20-29': 118273, + '30-39': 99451, + '40-49': 117324, + '50-59': 125415, + '60-69': 90557, + '70-79': 47535, + '80+': 25500}, + 'Saint Lucia': {'0-9': 21813, + '10-19': 24336, + '20-29': 32816, + '30-39': 28448, + '40-49': 25516, + '50-59': 23375, + '60-69': 14556, + '70-79': 8355, + '80+': 4412}, + 'Saint Vincent and the Grenadines': {'0-9': 15945, + '10-19': 17425, + '20-29': 17503, + '30-39': 15712, + '40-49': 14485, + '50-59': 13587, + '60-69': 9176, + '70-79': 4503, + '80+': 2604}, + 'Samoa': {'0-9': 51121, + '10-19': 42003, + '20-29': 31297, + '30-39': 22010, + '40-49': 19559, + '50-59': 16472, + '60-69': 9961, + '70-79': 4578, + '80+': 1413}, + 'Sao Tome and Principe': {'0-9': 62410, + '10-19': 54109, + '20-29': 33623, + '30-39': 26630, + '40-49': 18680, + '50-59': 12781, + '60-69': 7083, + '70-79': 2763, + '80+': 1080}, + 'Saudi Arabia': {'0-9': 5956215, + '10-19': 4860281, + '20-29': 5354763, + '30-39': 6980363, + '40-49': 6408790, + '50-59': 3216573, + '60-69': 1373521, + '70-79': 493856, + '80+': 169509}, + 'Senegal': {'0-9': 5032581, + '10-19': 3863701, + '20-29': 2823536, + '30-39': 2051292, + '40-49': 1331829, + '50-59': 834697, + '60-69': 505761, + '70-79': 239181, + '80+': 61349}, + 'Serbia': {'0-9': 855818, + '10-19': 999733, + '20-29': 1102466, + '30-39': 1214888, + '40-49': 1229894, + '50-59': 1121507, + '60-69': 1142469, + '70-79': 729682, + '80+': 340914}, + 'Seychelles': {'0-9': 15935, + '10-19': 13867, + '20-29': 13431, + '30-39': 14488, + '40-49': 14873, + '50-59': 12978, + '60-69': 7911, + '70-79': 3205, + '80+': 1659}, + 'Sierra Leone': {'0-9': 2225885, + '10-19': 1867195, + '20-29': 1405514, + '30-39': 1017051, + '40-49': 672892, + '50-59': 419133, + '60-69': 234027, + '70-79': 108809, + '80+': 26477}, + 'Singapore': {'0-9': 479039, + '10-19': 505791, + '20-29': 833056, + '30-39': 896616, + '40-49': 964875, + '50-59': 946223, + '60-69': 799325, + '70-79': 289630, + '80+': 135787}, + 'Slovakia': {'0-9': 566590, + '10-19': 545493, + '20-29': 655787, + '30-39': 847604, + '40-49': 861400, + '50-59': 709218, + '60-69': 695209, + '70-79': 398709, + '80+': 179632}, + 'Slovenia': {'0-9': 210171, + '10-19': 196378, + '20-29': 205492, + '30-39': 283648, + '40-49': 305327, + '50-59': 301204, + '60-69': 284942, + '70-79': 177497, + '80+': 114279}, + 'Solomon Islands': {'0-9': 196169, + '10-19': 148827, + '20-29': 111830, + '30-39': 82051, + '40-49': 68670, + '50-59': 40695, + '60-69': 22979, + '70-79': 11993, + '80+': 3670}, + 'Somalia': {'0-9': 5215365, + '10-19': 3937588, + '20-29': 2693878, + '30-39': 1534402, + '40-49': 1053897, + '50-59': 733973, + '60-69': 462792, + '70-79': 210106, + '80+': 51221}, + 'South Africa': {'0-9': 11585606, + '10-19': 10409174, + '20-29': 10141490, + '30-39': 10155325, + '40-49': 7043274, + '50-59': 4911530, + '60-69': 3164440, + '70-79': 1476055, + '80+': 421796}, + 'South Sudan': {'0-9': 3245684, + '10-19': 2581903, + '20-29': 1962948, + '30-39': 1334152, + '40-49': 896838, + '50-59': 595522, + '60-69': 344938, + '70-79': 182625, + '80+': 49115}, + 'Spain': {'0-9': 4234486, + '10-19': 4736076, + '20-29': 4617599, + '30-39': 5901992, + '40-49': 7938499, + '50-59': 7046327, + '60-69': 5340654, + '70-79': 4015304, + '80+': 2923841}, + 'Sri Lanka': {'0-9': 3350035, + '10-19': 3386220, + '20-29': 2901858, + '30-39': 2820020, + '40-49': 2881105, + '50-59': 2554817, + '60-69': 2013196, + '70-79': 1146337, + '80+': 359661}, + 'State of Palestine': {'0-9': 1364529, + '10-19': 1109494, + '20-29': 965726, + '30-39': 664295, + '40-49': 448138, + '50-59': 297319, + '60-69': 151853, + '70-79': 77833, + '80+': 22227}, + 'Sudan': {'0-9': 12128803, + '10-19': 10123658, + '20-29': 7627155, + '30-39': 5203245, + '40-49': 3727317, + '50-59': 2552951, + '60-69': 1535958, + '70-79': 733051, + '80+': 217121}, + 'Suriname': {'0-9': 104833, + '10-19': 102229, + '20-29': 95774, + '30-39': 82789, + '40-49': 72724, + '50-59': 64826, + '60-69': 36928, + '70-79': 18682, + '80+': 7847}, + 'Sweden': {'0-9': 1193952, + '10-19': 1127126, + '20-29': 1276929, + '30-39': 1320296, + '40-49': 1264123, + '50-59': 1296645, + '60-69': 1093869, + '70-79': 994243, + '80+': 532082}, + 'Switzerland': {'0-9': 884945, + '10-19': 834866, + '20-29': 1039727, + '30-39': 1219227, + '40-49': 1166590, + '50-59': 1320623, + '60-69': 977436, + '70-79': 751994, + '80+': 459214}, + 'Syrian Arab Republic': {'0-9': 3635906, + '10-19': 3325125, + '20-29': 3099981, + '30-39': 2907195, + '40-49': 1928900, + '50-59': 1285347, + '60-69': 822366, + '70-79': 355547, + '80+': 140291}, + 'Taiwan Province of China': {'0-9': 2052885, + '10-19': 2188808, + '20-29': 3120353, + '30-39': 3548586, + '40-49': 3787845, + '50-59': 3659220, + '60-69': 3101016, + '70-79': 1488802, + '80+': 869260}, + 'Tajikistan': {'0-9': 2577608, + '10-19': 1788370, + '20-29': 1648520, + '30-39': 1390332, + '40-49': 882400, + '50-59': 700892, + '60-69': 387890, + '70-79': 117606, + '80+': 44027}, + 'Thailand': {'0-9': 7439833, + '10-19': 8492312, + '20-29': 9630311, + '30-39': 9229726, + '40-49': 10914254, + '50-59': 10681391, + '60-69': 7624358, + '70-79': 3866567, + '80+': 1921226}, + 'The former Yugoslav Republic of Macedonia': {'0-9': 227550, + '10-19': 233451, + '20-29': 282982, + '30-39': 325975, + '40-49': 299904, + '50-59': 282831, + '60-69': 244647, + '70-79': 133880, + '80+': 52154}, + 'Timor-Leste': {'0-9': 331877, + '10-19': 306717, + '20-29': 244908, + '30-39': 159027, + '40-49': 100789, + '50-59': 88473, + '60-69': 50144, + '70-79': 28916, + '80+': 7594}, + 'Togo': {'0-9': 2340180, + '10-19': 1914993, + '20-29': 1375262, + '30-39': 1064553, + '40-49': 744517, + '50-59': 450710, + '60-69': 255935, + '70-79': 111491, + '80+': 21083}, + 'Tonga': {'0-9': 24640, + '10-19': 23525, + '20-29': 17138, + '30-39': 12181, + '40-49': 10289, + '50-59': 8701, + '60-69': 5304, + '70-79': 2791, + '80+': 1126}, + 'Trinidad and Tobago': {'0-9': 184450, + '10-19': 185807, + '20-29': 183001, + '30-39': 242864, + '40-49': 191443, + '50-59': 175059, + '60-69': 135895, + '70-79': 73653, + '80+': 27316}, + 'Tunisia': {'0-9': 2017758, + '10-19': 1639937, + '20-29': 1725345, + '30-39': 1914066, + '40-49': 1572474, + '50-59': 1361507, + '60-69': 962594, + '70-79': 424105, + '80+': 200832}, + 'Turkey': {'0-9': 13419270, + '10-19': 13595150, + '20-29': 13174164, + '30-39': 12774732, + '40-49': 11446581, + '50-59': 8908423, + '60-69': 6192391, + '70-79': 3353577, + '80+': 1474778}, + 'Turkmenistan': {'0-9': 1332932, + '10-19': 1008742, + '20-29': 1009792, + '30-39': 957887, + '40-49': 697821, + '50-59': 535461, + '60-69': 334447, + '70-79': 103460, + '80+': 50658}, + 'Uganda': {'0-9': 14855951, + '10-19': 11449426, + '20-29': 7872675, + '30-39': 5101102, + '40-49': 3133402, + '50-59': 1852437, + '60-69': 974327, + '70-79': 411999, + '80+': 89688}, + 'Ukraine': {'0-9': 4589511, + '10-19': 4383518, + '20-29': 4898491, + '30-39': 7208959, + '40-49': 6406401, + '50-59': 5906740, + '60-69': 5539857, + '70-79': 2983432, + '80+': 1816853}, + 'United Arab Emirates': {'0-9': 1011712, + '10-19': 842993, + '20-29': 2149345, + '30-39': 3169316, + '40-49': 1608106, + '50-59': 797911, + '60-69': 242705, + '70-79': 55883, + '80+': 12431}, + 'United Kingdom of Great Britain and Northern Ireland': {'0-9': 8044056, + '10-19': 7642475, + '20-29': 8558707, + '30-39': 9295025, + '40-49': 8604251, + '50-59': 9173467, + '60-69': 7286778, + '70-79': 5830636, + '80+': 3450616}, + 'United Republic of Tanzania': {'0-9': 18362315, + '10-19': 14089046, + '20-29': 9846249, + '30-39': 7161926, + '40-49': 4820729, + '50-59': 2926636, + '60-69': 1622801, + '70-79': 741234, + '80+': 163282}, + 'United States Virgin Islands': {'0-9': 12866, + '10-19': 14018, + '20-29': 12732, + '30-39': 9733, + '40-49': 11766, + '50-59': 14450, + '60-69': 14020, + '70-79': 10901, + '80+': 3939}, + 'United States of America': {'0-9': 39721484, + '10-19': 42332393, + '20-29': 46094077, + '30-39': 44668271, + '40-49': 40348398, + '50-59': 42120077, + '60-69': 38488173, + '70-79': 24082598, + '80+': 13147180}, + 'Uruguay': {'0-9': 473071, + '10-19': 478929, + '20-29': 511559, + '30-39': 461146, + '40-49': 455021, + '50-59': 391074, + '60-69': 327921, + '70-79': 220267, + '80+': 154741}, + 'Uzbekistan': {'0-9': 6713724, + '10-19': 5460857, + '20-29': 5946988, + '30-39': 5577195, + '40-49': 3930502, + '50-59': 3068759, + '60-69': 1939630, + '70-79': 572151, + '80+': 259397}, + 'Vanuatu': {'0-9': 80884, + '10-19': 66925, + '20-29': 50769, + '30-39': 41001, + '40-49': 29192, + '50-59': 20541, + '60-69': 11438, + '70-79': 4837, + '80+': 1558}, + 'Venezuela (Bolivarian Republic of)': {'0-9': 5094601, + '10-19': 5158570, + '20-29': 4130338, + '30-39': 4027919, + '40-49': 3564976, + '50-59': 3014982, + '60-69': 2042554, + '70-79': 989858, + '80+': 412141}, + 'Viet Nam': {'0-9': 15478572, + '10-19': 13599041, + '20-29': 15389495, + '30-39': 16200926, + '40-49': 13572964, + '50-59': 11109965, + '60-69': 7342685, + '70-79': 2778470, + '80+': 1866461}, + 'Western Sahara': {'0-9': 112592, + '10-19': 98369, + '20-29': 104987, + '30-39': 108717, + '40-49': 82796, + '50-59': 51955, + '60-69': 28373, + '70-79': 7614, + '80+': 1936}, + 'Yemen': {'0-9': 8033406, + '10-19': 6750274, + '20-29': 5732747, + '30-39': 4140438, + '40-49': 2362805, + '50-59': 1422834, + '60-69': 879448, + '70-79': 403471, + '80+': 100540}, + 'Zambia': {'0-9': 5663541, + '10-19': 4550182, + '20-29': 3180383, + '30-39': 2185196, + '40-49': 1413887, + '50-59': 761262, + '60-69': 403835, + '70-79': 179963, + '80+': 45706}, + 'Zimbabwe': {'0-9': 4308157, + '10-19': 3559952, + '20-29': 2482990, + '30-39': 1867477, + '40-49': 1257821, + '50-59': 698090, + '60-69': 425415, + '70-79': 200359, + '80+': 62663} + } \ No newline at end of file diff --git a/covasim/data/household_size_data.py b/covasim/data/household_size_data.py index 3b5f4d24f..2f0e0cd40 100644 --- a/covasim/data/household_size_data.py +++ b/covasim/data/household_size_data.py @@ -1,187 +1,186 @@ -def get(): - ''' - This is the following file: +''' +This is the following file: - https://population.un.org/household/exceldata/population_division_UN_Houseshold_Size_and_Composition_2019.xlsx - - expressed as a function. - ''' - data = { - 'Afghanistan' : 8.036, - 'Albania' : 3.299, - 'Angola' : 4.815, - 'Argentina' : 3.258, - 'Armenia' : 3.542, - 'Aruba' : 2.889, - 'Australia' : 2.546, - 'Austria' : 2.271, - 'Azerbaijan' : 4.548, - 'Bahamas' : 3.395, - 'Bangladesh' : 4.469, - 'Belarus' : 2.482, - 'Belgium' : 2.362, - 'Benin' : 5.186, - 'Bermuda' : 2.262, - 'Bolivia (Plurinational State of)' : 3.530, - 'Botswana' : 3.524, - 'Brazil' : 3.311, - 'Bulgaria' : 2.337, - 'Burkina Faso' : 5.924, - 'Burundi' : 4.830, - 'Cambodia' : 4.611, - 'Cameroon' : 4.992, - 'Canada' : 2.448, - 'Central African Republic' : 4.906, - 'Chad' : 5.777, - 'Chile' : 3.576, - 'China' : 3.384, - 'China, Hong Kong SAR' : 2.834, - 'China, Macao SAR' : 3.066, - 'Colombia' : 3.526, - 'Comoros' : 5.371, - 'Congo' : 4.307, - 'Costa Rica' : 3.461, - 'Croatia' : 2.795, - 'Cuba' : 3.136, - 'Cyprus' : 2.747, - 'Czechia' : 2.395, - "Côte d'Ivoire" : 5.090, - "Dem. People's Rep. of Korea" : 3.929, - 'Dem. Republic of the Congo' : 5.302, - 'Dominican Republic' : 3.477, - 'Ecuador' : 3.779, - 'Egypt' : 4.130, - 'El Salvador' : 4.069, - 'Estonia' : 2.297, - 'Ethiopia' : 4.614, - 'Fiji' : 4.572, - 'Finland' : 2.074, - 'France' : 2.222, - 'French Guiana' : 3.454, - 'Gabon' : 4.097, - 'Gambia' : 8.229, - 'Georgia' : 3.337, - 'Germany' : 2.046, - 'Ghana' : 3.492, - 'Greece' : 2.440, - 'Guadeloupe' : 2.296, - 'Guatemala' : 4.805, - 'Guinea' : 6.250, - 'Guyana' : 3.795, - 'Haiti' : 4.293, - 'Honduras' : 4.467, - 'Hungary' : 2.603, - 'India' : 4.572, - 'Indonesia' : 3.859, - 'Iran (Islamic Republic of)' : 3.492, - 'Iraq' : 7.703, - 'Ireland' : 2.766, - 'Isle of Man' : 2.283, - 'Israel' : 3.141, - 'Italy' : 2.399, - 'Jamaica' : 3.060, - 'Japan' : 2.330, - 'Jordan' : 4.718, - 'Kazakhstan' : 3.496, - 'Kenya' : 3.638, - 'Kyrgyzstan' : 4.214, - "Lao People's Dem. Republic" : 5.765, - 'Latvia' : 2.578, - 'Lesotho' : 3.344, - 'Liberia' : 4.945, - 'Liechtenstein' : 2.320, - 'Lithuania' : 2.320, - 'Luxembourg' : 2.412, - 'Madagascar' : 4.949, - 'Malawi' : 4.508, - 'Malaysia' : 4.557, - 'Maldives' : 5.399, - 'Mali' : 5.811, - 'Malta' : 2.852, - 'Martinique' : 2.248, - 'Mauritius' : 3.475, - 'Mayotte' : 4.102, - 'Mexico' : 3.740, - 'Mongolia' : 4.321, - 'Montenegro' : 3.214, - 'Morocco' : 5.236, - 'Mozambique' : 4.366, - 'Myanmar' : 4.223, - 'Namibia' : 4.238, - 'Nepal' : 4.239, - 'Netherlands' : 2.226, - 'New Zealand' : 2.672, - 'Nicaragua' : 4.919, - 'Niger' : 5.916, - 'Nigeria' : 4.901, - 'Norway' : 2.215, - 'Oman' : 8.017, - 'Pakistan' : 6.804, - 'Panama' : 3.670, - 'Papua New Guinea' : 5.430, - 'Paraguay' : 4.632, - 'Peru' : 3.752, - 'Philippines' : 4.226, - 'Poland' : 2.806, - 'Portugal' : 2.655, - 'Puerto Rico' : 2.670, - 'Republic of Korea' : 2.529, - 'Republic of Moldova' : 2.888, - 'Romania' : 2.879, - 'Russian Federation' : 2.584, - 'Rwanda' : 4.259, - 'Réunion' : 2.643, - 'Saint-Barthélemy' : 2.424, - 'Saint-Martin (French part)' : 2.564, - 'Samoa' : 6.751, - 'Sao Tome and Principe' : 3.836, - 'Senegal' : 8.661, - 'Serbia' : 2.879, - 'Seychelles' : 3.778, - 'Sierra Leone' : 5.899, - 'Singapore' : 3.291, - 'Sint Maarten (Dutch part)' : 2.579, - 'Slovakia' : 2.801, - 'Slovenia' : 2.467, - 'South Africa' : 3.362, - 'South Sudan' : 5.947, - 'Spain' : 2.694, - 'State of Palestine' : 5.476, - 'Sudan' : 5.590, - 'Suriname' : 3.940, - 'Swaziland' : 4.737, - 'Switzerland' : 2.212, - 'Tajikistan' : 5.993, - 'Thailand' : 3.693, - 'Timor-Leste' : 5.267, - 'Togo' : 4.551, - 'Tokelau' : 5.243, - 'Trinidad and Tobago' : 3.290, - 'Turkey' : 4.071, - 'Uganda' : 4.534, - 'Ukraine' : 2.458, - 'United Kingdom' : 2.265, - 'United Republic of Tanzania' : 4.851, - 'United States of America' : 2.491, - 'Uruguay' : 2.781, - 'Uzbekistan' : 5.242, - 'Venezuela (Bolivarian Republic of)' : 4.331, - 'Viet Nam' : 3.783, - 'Yemen' : 6.672, - 'Zambia' : 5.130, - 'Zimbabwe' : 4.077, - 'Bolivia' : 3.530, - 'Burkina' : 5.924, - 'Iran' : 3.492, - 'Korea' : 2.529, - 'South Korea' : 2.529, - 'Moldova' : 2.888, - 'Russia' : 2.584, - 'Palestine' : 5.476, - 'Tanzania' : 4.851, - 'USA' : 2.491, - 'United States' : 2.491, - 'Venezuela' : 4.331, - 'Vietnam' : 3.783, - } - return data \ No newline at end of file +https://population.un.org/household/exceldata/population_division_UN_Houseshold_Size_and_Composition_2019.xlsx + +expressed as a function. +''' + +data = { + 'Afghanistan' : 8.036, + 'Albania' : 3.299, + 'Angola' : 4.815, + 'Argentina' : 3.258, + 'Armenia' : 3.542, + 'Aruba' : 2.889, + 'Australia' : 2.546, + 'Austria' : 2.271, + 'Azerbaijan' : 4.548, + 'Bahamas' : 3.395, + 'Bangladesh' : 4.469, + 'Belarus' : 2.482, + 'Belgium' : 2.362, + 'Benin' : 5.186, + 'Bermuda' : 2.262, + 'Bolivia (Plurinational State of)' : 3.530, + 'Botswana' : 3.524, + 'Brazil' : 3.311, + 'Bulgaria' : 2.337, + 'Burkina Faso' : 5.924, + 'Burundi' : 4.830, + 'Cambodia' : 4.611, + 'Cameroon' : 4.992, + 'Canada' : 2.448, + 'Central African Republic' : 4.906, + 'Chad' : 5.777, + 'Chile' : 3.576, + 'China' : 3.384, + 'China, Hong Kong SAR' : 2.834, + 'China, Macao SAR' : 3.066, + 'Colombia' : 3.526, + 'Comoros' : 5.371, + 'Congo' : 4.307, + 'Costa Rica' : 3.461, + 'Croatia' : 2.795, + 'Cuba' : 3.136, + 'Cyprus' : 2.747, + 'Czechia' : 2.395, + "Côte d'Ivoire" : 5.090, + "Dem. People's Rep. of Korea" : 3.929, + 'Dem. Republic of the Congo' : 5.302, + 'Dominican Republic' : 3.477, + 'Ecuador' : 3.779, + 'Egypt' : 4.130, + 'El Salvador' : 4.069, + 'Estonia' : 2.297, + 'Ethiopia' : 4.614, + 'Fiji' : 4.572, + 'Finland' : 2.074, + 'France' : 2.222, + 'French Guiana' : 3.454, + 'Gabon' : 4.097, + 'Gambia' : 8.229, + 'Georgia' : 3.337, + 'Germany' : 2.046, + 'Ghana' : 3.492, + 'Greece' : 2.440, + 'Guadeloupe' : 2.296, + 'Guatemala' : 4.805, + 'Guinea' : 6.250, + 'Guyana' : 3.795, + 'Haiti' : 4.293, + 'Honduras' : 4.467, + 'Hungary' : 2.603, + 'India' : 4.572, + 'Indonesia' : 3.859, + 'Iran (Islamic Republic of)' : 3.492, + 'Iraq' : 7.703, + 'Ireland' : 2.766, + 'Isle of Man' : 2.283, + 'Israel' : 3.141, + 'Italy' : 2.399, + 'Jamaica' : 3.060, + 'Japan' : 2.330, + 'Jordan' : 4.718, + 'Kazakhstan' : 3.496, + 'Kenya' : 3.638, + 'Kyrgyzstan' : 4.214, + "Lao People's Dem. Republic" : 5.765, + 'Latvia' : 2.578, + 'Lesotho' : 3.344, + 'Liberia' : 4.945, + 'Liechtenstein' : 2.320, + 'Lithuania' : 2.320, + 'Luxembourg' : 2.412, + 'Madagascar' : 4.949, + 'Malawi' : 4.508, + 'Malaysia' : 4.557, + 'Maldives' : 5.399, + 'Mali' : 5.811, + 'Malta' : 2.852, + 'Martinique' : 2.248, + 'Mauritius' : 3.475, + 'Mayotte' : 4.102, + 'Mexico' : 3.740, + 'Mongolia' : 4.321, + 'Montenegro' : 3.214, + 'Morocco' : 5.236, + 'Mozambique' : 4.366, + 'Myanmar' : 4.223, + 'Namibia' : 4.238, + 'Nepal' : 4.239, + 'Netherlands' : 2.226, + 'New Zealand' : 2.672, + 'Nicaragua' : 4.919, + 'Niger' : 5.916, + 'Nigeria' : 4.901, + 'Norway' : 2.215, + 'Oman' : 8.017, + 'Pakistan' : 6.804, + 'Panama' : 3.670, + 'Papua New Guinea' : 5.430, + 'Paraguay' : 4.632, + 'Peru' : 3.752, + 'Philippines' : 4.226, + 'Poland' : 2.806, + 'Portugal' : 2.655, + 'Puerto Rico' : 2.670, + 'Republic of Korea' : 2.529, + 'Republic of Moldova' : 2.888, + 'Romania' : 2.879, + 'Russian Federation' : 2.584, + 'Rwanda' : 4.259, + 'Réunion' : 2.643, + 'Saint-Barthélemy' : 2.424, + 'Saint-Martin (French part)' : 2.564, + 'Samoa' : 6.751, + 'Sao Tome and Principe' : 3.836, + 'Senegal' : 8.661, + 'Serbia' : 2.879, + 'Seychelles' : 3.778, + 'Sierra Leone' : 5.899, + 'Singapore' : 3.291, + 'Sint Maarten (Dutch part)' : 2.579, + 'Slovakia' : 2.801, + 'Slovenia' : 2.467, + 'South Africa' : 3.362, + 'South Sudan' : 5.947, + 'Spain' : 2.694, + 'State of Palestine' : 5.476, + 'Sudan' : 5.590, + 'Suriname' : 3.940, + 'Swaziland' : 4.737, + 'Switzerland' : 2.212, + 'Tajikistan' : 5.993, + 'Thailand' : 3.693, + 'Timor-Leste' : 5.267, + 'Togo' : 4.551, + 'Tokelau' : 5.243, + 'Trinidad and Tobago' : 3.290, + 'Turkey' : 4.071, + 'Uganda' : 4.534, + 'Ukraine' : 2.458, + 'United Kingdom' : 2.265, + 'United Republic of Tanzania' : 4.851, + 'United States of America' : 2.491, + 'Uruguay' : 2.781, + 'Uzbekistan' : 5.242, + 'Venezuela (Bolivarian Republic of)' : 4.331, + 'Viet Nam' : 3.783, + 'Yemen' : 6.672, + 'Zambia' : 5.130, + 'Zimbabwe' : 4.077, + 'Bolivia' : 3.530, + 'Burkina' : 5.924, + 'Iran' : 3.492, + 'Korea' : 2.529, + 'South Korea' : 2.529, + 'Moldova' : 2.888, + 'Russia' : 2.584, + 'Palestine' : 5.476, + 'Tanzania' : 4.851, + 'USA' : 2.491, + 'United States' : 2.491, + 'Venezuela' : 4.331, + 'Vietnam' : 3.783, + } \ No newline at end of file diff --git a/covasim/data/loaders.py b/covasim/data/loaders.py index b9134594b..3740d2ec4 100644 --- a/covasim/data/loaders.py +++ b/covasim/data/loaders.py @@ -9,7 +9,7 @@ from . import state_age_data as sad from . import household_size_data as hsd -__all__ = ['get_country_aliases', 'map_entries', 'get_valid_locations', 'get_age_distribution', 'get_household_size'] +__all__ = ['get_country_aliases', 'map_entries', 'show_locations', 'get_age_distribution', 'get_household_size'] def get_country_aliases(): @@ -88,9 +88,9 @@ def map_entries(json, location): return entries -def get_valid_locations(location=None, output=False): +def show_locations(location=None, output=False): ''' - Print a list of valid locations. + Print a list of available locations. Args: location (str): if provided, only check if this location is in the list @@ -98,16 +98,16 @@ def get_valid_locations(location=None, output=False): **Examples**:: - cv.data.get_valid_locations() # Print a list of valid locations - cv.data.get_valid_locations('lithuania') # Check if Lithuania is a valid location - cv.data.get_valid_locations('Viet-Nam') # Check if Viet-Nam is a valid location + cv.data.show_locations() # Print a list of valid locations + cv.data.show_locations('lithuania') # Check if Lithuania is a valid location + cv.data.show_locations('Viet-Nam') # Check if Viet-Nam is a valid location ''' - country_json = cad.get() - state_json = sad.get() + country_json = sc.dcp(cad.data) + state_json = sc.dcp(sad.data) aliases = get_country_aliases() age_data = sc.mergedicts(state_json, country_json, aliases) # Countries will overwrite states, e.g. Georgia - household_data = hsd.get() + household_data = sc.dcp(hsd.data) loclist = sc.objdict() loclist.age_distributions = sorted(list(age_data.keys())) @@ -146,8 +146,8 @@ def get_age_distribution(location=None): ''' # Load the raw data - country_json = cad.get() - state_json = sad.get() + country_json = sc.dcp(cad.data) + state_json = sc.dcp(sad.data) json = sc.mergedicts(state_json, country_json) # Countries will overwrite states, e.g. Georgia entries = map_entries(json, location) @@ -183,7 +183,7 @@ def get_household_size(location=None): house_size (float): Size of household, or dict if multiple locations ''' # Load the raw data - json = hsd.get() + json = sc.dcp(hsd.data) result = map_entries(json, location) if len(result) == 1: diff --git a/covasim/data/state_age_data.py b/covasim/data/state_age_data.py index 5fe740ecf..9fd36eabb 100644 --- a/covasim/data/state_age_data.py +++ b/covasim/data/state_age_data.py @@ -1,944 +1,942 @@ -def get(): - """ - This data is translated from the US Census csv to - the new json format expressed as a function - """ - data = { - 'USA-Alabama': {'0-5': 5.9, - '5-9': 5.9, - '10-14': 6.6, - '15-19': 6.8, - '20-24': 6.5, - '25-29': 6.8, - '30-34': 6.2, - '35-39': 6.0, - '40-44': 6.1, - '45-49': 6.3, - '50-54': 6.5, - '55-59': 6.8, - '60-64': 6.5, - '65-69': 5.5, - '70-74': 4.6, - '75-79': 3.1, - '80-84': 2.0, - '85+': 1.7}, - 'USA-Alaska': {'0-5': 7.1, - '5-9': 7.1, - '10-14': 6.7, - '15-19': 6.6, - '20-24': 6.7, - '25-29': 8.5, - '30-34': 7.5, - '35-39': 7.3, - '40-44': 5.9, - '45-49': 5.8, - '50-54': 6.4, - '55-59': 6.4, - '60-64': 6.2, - '65-69': 5.1, - '70-74': 3.0, - '75-79': 1.7, - '80-84': 1.1, - '85+': 1.0}, - 'USA-Arizona': {'0-5': 6.1, - '5-9': 6.2, - '10-14': 6.8, - '15-19': 6.7, - '20-24': 6.8, - '25-29': 7.2, - '30-34': 6.5, - '35-39': 6.3, - '40-44': 6.0, - '45-49': 6.0, - '50-54': 5.8, - '55-59': 6.0, - '60-64': 6.1, - '65-69': 5.5, - '70-74': 4.7, - '75-79': 3.4, - '80-84': 2.1, - '85+': 1.9}, - 'USA-Arkansas': {'0-5': 6.2, - '5-9': 6.4, - '10-14': 6.8, - '15-19': 6.9, - '20-24': 6.6, - '25-29': 6.8, - '30-34': 6.3, - '35-39': 6.3, - '40-44': 5.9, - '45-49': 6.1, - '50-54': 6.2, - '55-59': 6.5, - '60-64': 6.2, - '65-69': 5.4, - '70-74': 4.5, - '75-79': 3.2, - '80-84': 1.9, - '85+': 1.9}, - 'USA-California': {'0-5': 6.1, - '5-9': 6.1, - '10-14': 6.7, - '15-19': 6.5, - '20-24': 6.9, - '25-29': 7.9, - '30-34': 7.4, - '35-39': 7.0, - '40-44': 6.3, - '45-49': 6.5, - '50-54': 6.3, - '55-59': 6.3, - '60-64': 5.8, - '65-69': 4.7, - '70-74': 3.6, - '75-79': 2.5, - '80-84': 1.7, - '85+': 1.8}, - 'USA-Colorado': {'0-5': 5.9, - '5-9': 6.2, - '10-14': 6.4, - '15-19': 6.5, - '20-24': 6.6, - '25-29': 7.9, - '30-34': 7.8, - '35-39': 7.1, - '40-44': 6.6, - '45-49': 6.5, - '50-54': 6.0, - '55-59': 6.4, - '60-64': 6.1, - '65-69': 5.0, - '70-74': 3.8, - '75-79': 2.3, - '80-84': 1.5, - '85+': 1.5}, - 'USA-Connecticut': {'0-5': 5.1, - '5-9': 5.4, - '10-14': 6.3, - '15-19': 6.8, - '20-24': 6.7, - '25-29': 6.2, - '30-34': 6.3, - '35-39': 6.0, - '40-44': 5.9, - '45-49': 6.6, - '50-54': 7.3, - '55-59': 7.3, - '60-64': 7.1, - '65-69': 5.2, - '70-74': 4.4, - '75-79': 3.1, - '80-84': 2.0, - '85+': 2.5}, - 'USA-Delaware': {'0-5': 5.6, - '5-9': 5.4, - '10-14': 6.5, - '15-19': 6.1, - '20-24': 6.2, - '25-29': 6.8, - '30-34': 6.3, - '35-39': 6.1, - '40-44': 5.5, - '45-49': 6.0, - '50-54': 6.7, - '55-59': 7.1, - '60-64': 7.0, - '65-69': 6.2, - '70-74': 5.0, - '75-79': 3.8, - '80-84': 1.8, - '85+': 1.9}, - 'USA-District of Columbia': {'0-5': 6.5, - '5-9': 4.7, - '10-14': 4.8, - '15-19': 5.3, - '20-24': 7.5, - '25-29': 11.7, - '30-34': 11.5, - '35-39': 9.0, - '40-44': 6.0, - '45-49': 5.6, - '50-54': 5.2, - '55-59': 5.2, - '60-64': 4.7, - '65-69': 3.7, - '70-74': 3.3, - '75-79': 2.3, - '80-84': 1.4, - '85+': 1.6}, - 'USA-Florida': {'0-5': 5.3, - '5-9': 5.3, - '10-14': 5.8, - '15-19': 5.8, - '20-24': 5.9, - '25-29': 6.7, - '30-34': 6.3, - '35-39': 6.2, - '40-44': 5.9, - '45-49': 6.3, - '50-54': 6.5, - '55-59': 6.8, - '60-64': 6.6, - '65-69': 6.1, - '70-74': 5.2, - '75-79': 3.9, - '80-84': 2.6, - '85+': 2.6}, - 'USA-Georgia': {'0-5': 6.1, - '5-9': 6.5, - '10-14': 7.0, - '15-19': 7.2, - '20-24': 6.8, - '25-29': 7.1, - '30-34': 6.6, - '35-39': 6.8, - '40-44': 6.5, - '45-49': 6.8, - '50-54': 6.5, - '55-59': 6.3, - '60-64': 5.8, - '65-69': 4.7, - '70-74': 3.8, - '75-79': 2.5, - '80-84': 1.5, - '85+': 1.4}, - 'USA-Hawaii': {'0-5': 6.2, - '5-9': 5.9, - '10-14': 6.0, - '15-19': 5.5, - '20-24': 6.4, - '25-29': 7.3, - '30-34': 6.9, - '35-39': 6.7, - '40-44': 6.1, - '45-49': 6.0, - '50-54': 6.0, - '55-59': 6.1, - '60-64': 6.6, - '65-69': 6.0, - '70-74': 4.6, - '75-79': 2.9, - '80-84': 2.2, - '85+': 2.8}, - 'USA-Idaho': {'0-5': 6.5, - '5-9': 7.1, - '10-14': 7.4, - '15-19': 7.2, - '20-24': 6.6, - '25-29': 6.7, - '30-34': 6.3, - '35-39': 6.3, - '40-44': 6.2, - '45-49': 5.9, - '50-54': 5.6, - '55-59': 6.4, - '60-64': 5.9, - '65-69': 5.5, - '70-74': 4.1, - '75-79': 3.0, - '80-84': 1.6, - '85+': 1.7}, - 'USA-Illinois': {'0-5': 6.0, - '5-9': 6.0, - '10-14': 6.6, - '15-19': 6.6, - '20-24': 6.6, - '25-29': 7.1, - '30-34': 6.8, - '35-39': 6.6, - '40-44': 6.3, - '45-49': 6.4, - '50-54': 6.4, - '55-59': 6.7, - '60-64': 6.4, - '65-69': 5.0, - '70-74': 3.9, - '75-79': 2.8, - '80-84': 1.8, - '85+': 2.0}, - 'USA-Indiana': {'0-5': 6.2, - '5-9': 6.4, - '10-14': 6.7, - '15-19': 6.9, - '20-24': 7.0, - '25-29': 6.8, - '30-34': 6.2, - '35-39': 6.5, - '40-44': 5.8, - '45-49': 6.2, - '50-54': 6.3, - '55-59': 6.7, - '60-64': 6.4, - '65-69': 5.2, - '70-74': 3.9, - '75-79': 2.8, - '80-84': 1.8, - '85+': 1.9}, - 'USA-Iowa': {'0-5': 6.3, - '5-9': 6.3, - '10-14': 6.8, - '15-19': 7.0, - '20-24': 7.0, - '25-29': 6.4, - '30-34': 6.1, - '35-39': 6.6, - '40-44': 5.5, - '45-49': 5.8, - '50-54': 5.9, - '55-59': 6.8, - '60-64': 6.5, - '65-69': 5.4, - '70-74': 4.1, - '75-79': 3.0, - '80-84': 2.2, - '85+': 2.4}, - 'USA-Kansas': {'0-5': 6.4, - '5-9': 6.5, - '10-14': 7.2, - '15-19': 7.0, - '20-24': 7.2, - '25-29': 6.6, - '30-34': 6.3, - '35-39': 6.4, - '40-44': 5.9, - '45-49': 5.8, - '50-54': 5.9, - '55-59': 6.5, - '60-64': 6.3, - '65-69': 5.4, - '70-74': 3.7, - '75-79': 2.7, - '80-84': 1.9, - '85+': 2.2}, - 'USA-Kentucky': {'0-5': 6.1, - '5-9': 6.3, - '10-14': 6.4, - '15-19': 6.5, - '20-24': 6.7, - '25-29': 6.9, - '30-34': 6.1, - '35-39': 6.3, - '40-44': 6.1, - '45-49': 6.4, - '50-54': 6.5, - '55-59': 6.8, - '60-64': 6.6, - '65-69': 5.5, - '70-74': 4.3, - '75-79': 2.9, - '80-84': 2.0, - '85+': 1.8}, - 'USA-Louisiana': {'0-5': 6.5, - '5-9': 6.4, - '10-14': 6.8, - '15-19': 6.6, - '20-24': 6.6, - '25-29': 7.1, - '30-34': 6.8, - '35-39': 6.8, - '40-44': 5.8, - '45-49': 6.0, - '50-54': 6.2, - '55-59': 6.5, - '60-64': 6.4, - '65-69': 5.4, - '70-74': 3.9, - '75-79': 2.8, - '80-84': 1.8, - '85+': 1.6}, - 'USA-Maine': {'0-5': 4.7, - '5-9': 5.1, - '10-14': 5.4, - '15-19': 5.8, - '20-24': 5.5, - '25-29': 6.0, - '30-34': 6.0, - '35-39': 6.0, - '40-44': 5.5, - '45-49': 6.3, - '50-54': 7.1, - '55-59': 7.9, - '60-64': 8.1, - '65-69': 6.9, - '70-74': 5.3, - '75-79': 3.4, - '80-84': 2.3, - '85+': 2.6}, - 'USA-Maryland': {'0-5': 6.0, - '5-9': 6.0, - '10-14': 6.4, - '15-19': 6.3, - '20-24': 6.4, - '25-29': 6.9, - '30-34': 6.8, - '35-39': 6.8, - '40-44': 6.0, - '45-49': 6.6, - '50-54': 7.0, - '55-59': 6.9, - '60-64': 6.5, - '65-69': 5.0, - '70-74': 4.0, - '75-79': 2.8, - '80-84': 1.8, - '85+': 1.8}, - 'USA-Massachusetts': {'0-5': 5.2, - '5-9': 5.4, - '10-14': 5.7, - '15-19': 6.6, - '20-24': 7.1, - '25-29': 7.3, - '30-34': 7.0, - '35-39': 6.3, - '40-44': 5.9, - '45-49': 6.4, - '50-54': 6.9, - '55-59': 7.1, - '60-64': 6.5, - '65-69': 5.3, - '70-74': 4.2, - '75-79': 2.8, - '80-84': 1.9, - '85+': 2.2}, - 'USA-Michigan': {'0-5': 5.7, - '5-9': 5.9, - '10-14': 6.2, - '15-19': 6.6, - '20-24': 6.9, - '25-29': 6.9, - '30-34': 6.0, - '35-39': 6.0, - '40-44': 5.6, - '45-49': 6.3, - '50-54': 6.6, - '55-59': 7.0, - '60-64': 7.0, - '65-69': 5.7, - '70-74': 4.4, - '75-79': 3.1, - '80-84': 2.0, - '85+': 2.0}, - 'USA-Minnesota': {'0-5': 6.3, - '5-9': 6.4, - '10-14': 6.6, - '15-19': 6.4, - '20-24': 6.4, - '25-29': 6.7, - '30-34': 6.8, - '35-39': 6.8, - '40-44': 5.9, - '45-49': 6.0, - '50-54': 6.3, - '55-59': 7.1, - '60-64': 6.3, - '65-69': 5.3, - '70-74': 3.8, - '75-79': 2.8, - '80-84': 1.9, - '85+': 2.1}, - 'USA-Mississippi': {'0-5': 6.0, - '5-9': 6.4, - '10-14': 7.2, - '15-19': 7.3, - '20-24': 6.9, - '25-29': 6.6, - '30-34': 6.0, - '35-39': 6.7, - '40-44': 6.0, - '45-49': 6.0, - '50-54': 6.1, - '55-59': 6.4, - '60-64': 6.5, - '65-69': 5.2, - '70-74': 4.3, - '75-79': 3.0, - '80-84': 1.8, - '85+': 1.6}, - 'USA-Missouri': {'0-5': 6.0, - '5-9': 6.1, - '10-14': 6.5, - '15-19': 6.4, - '20-24': 6.6, - '25-29': 6.9, - '30-34': 6.5, - '35-39': 6.4, - '40-44': 5.7, - '45-49': 6.0, - '50-54': 6.2, - '55-59': 6.8, - '60-64': 6.7, - '65-69': 5.3, - '70-74': 4.4, - '75-79': 3.1, - '80-84': 2.0, - '85+': 2.0}, - 'USA-Montana': {'0-5': 5.8, - '5-9': 5.8, - '10-14': 6.4, - '15-19': 6.3, - '20-24': 6.4, - '25-29': 6.5, - '30-34': 6.1, - '35-39': 6.5, - '40-44': 5.6, - '45-49': 5.6, - '50-54': 5.8, - '55-59': 6.8, - '60-64': 7.5, - '65-69': 6.5, - '70-74': 4.9, - '75-79': 3.5, - '80-84': 2.0, - '85+': 2.0}, - 'USA-Nebraska': {'0-5': 6.8, - '5-9': 6.7, - '10-14': 7.1, - '15-19': 6.9, - '20-24': 6.9, - '25-29': 6.6, - '30-34': 6.7, - '35-39': 6.8, - '40-44': 5.8, - '45-49': 5.7, - '50-54': 5.6, - '55-59': 6.4, - '60-64': 6.2, - '65-69': 5.3, - '70-74': 3.7, - '75-79': 2.6, - '80-84': 2.0, - '85+': 2.2}, - 'USA-Nevada': {'0-5': 6.1, - '5-9': 6.2, - '10-14': 6.6, - '15-19': 6.0, - '20-24': 5.9, - '25-29': 7.4, - '30-34': 7.1, - '35-39': 6.8, - '40-44': 6.5, - '45-49': 6.7, - '50-54': 6.4, - '55-59': 6.3, - '60-64': 6.1, - '65-69': 5.2, - '70-74': 4.4, - '75-79': 2.8, - '80-84': 1.7, - '85+': 1.5}, - 'USA-New Hampshire': {'0-5': 4.6, - '5-9': 5.1, - '10-14': 5.7, - '15-19': 6.8, - '20-24': 6.3, - '25-29': 6.3, - '30-34': 6.1, - '35-39': 5.9, - '40-44': 5.6, - '45-49': 6.6, - '50-54': 7.4, - '55-59': 8.2, - '60-64': 7.5, - '65-69': 6.1, - '70-74': 4.7, - '75-79': 3.1, - '80-84': 1.9, - '85+': 2.3}, - 'USA-New Jersey': {'0-5': 5.8, - '5-9': 5.8, - '10-14': 6.4, - '15-19': 6.2, - '20-24': 6.2, - '25-29': 6.5, - '30-34': 6.4, - '35-39': 6.6, - '40-44': 6.3, - '45-49': 6.7, - '50-54': 7.1, - '55-59': 7.1, - '60-64': 6.6, - '65-69': 5.1, - '70-74': 4.1, - '75-79': 2.9, - '80-84': 1.9, - '85+': 2.2}, - 'USA-New Mexico': {'0-5': 5.7, - '5-9': 6.1, - '10-14': 7.2, - '15-19': 6.8, - '20-24': 6.6, - '25-29': 6.7, - '30-34': 6.6, - '35-39': 6.5, - '40-44': 5.7, - '45-49': 5.7, - '50-54': 5.8, - '55-59': 6.5, - '60-64': 6.5, - '65-69': 5.8, - '70-74': 4.7, - '75-79': 3.1, - '80-84': 2.0, - '85+': 1.9}, - 'USA-New York': {'0-5': 5.8, - '5-9': 5.5, - '10-14': 5.9, - '15-19': 6.2, - '20-24': 6.6, - '25-29': 7.6, - '30-34': 7.1, - '35-39': 6.5, - '40-44': 6.0, - '45-49': 6.3, - '50-54': 6.8, - '55-59': 6.8, - '60-64': 6.5, - '65-69': 5.1, - '70-74': 4.2, - '75-79': 2.9, - '80-84': 2.0, - '85+': 2.2}, - 'USA-North Carolina': {'0-5': 5.8, - '5-9': 6.0, - '10-14': 6.5, - '15-19': 6.8, - '20-24': 6.6, - '25-29': 6.9, - '30-34': 6.4, - '35-39': 6.4, - '40-44': 6.2, - '45-49': 6.7, - '50-54': 6.6, - '55-59': 6.5, - '60-64': 6.4, - '65-69': 5.4, - '70-74': 4.4, - '75-79': 3.0, - '80-84': 1.8, - '85+': 1.7}, - 'USA-North Dakota': {'0-5': 6.9, - '5-9': 6.7, - '10-14': 6.2, - '15-19': 6.1, - '20-24': 8.2, - '25-29': 8.1, - '30-34': 7.3, - '35-39': 6.6, - '40-44': 5.3, - '45-49': 5.3, - '50-54': 5.4, - '55-59': 6.5, - '60-64': 6.0, - '65-69': 5.0, - '70-74': 3.5, - '75-79': 2.5, - '80-84': 2.0, - '85+': 2.4}, - 'USA-Ohio': {'0-5': 5.9, - '5-9': 5.9, - '10-14': 6.4, - '15-19': 6.6, - '20-24': 6.4, - '25-29': 6.8, - '30-34': 6.3, - '35-39': 6.2, - '40-44': 5.8, - '45-49': 6.3, - '50-54': 6.5, - '55-59': 7.0, - '60-64': 6.8, - '65-69': 5.6, - '70-74': 4.2, - '75-79': 3.1, - '80-84': 2.0, - '85+': 2.1}, - 'USA-Oklahoma': {'0-5': 6.5, - '5-9': 6.6, - '10-14': 7.1, - '15-19': 6.9, - '20-24': 6.8, - '25-29': 7.1, - '30-34': 6.6, - '35-39': 6.6, - '40-44': 5.8, - '45-49': 5.9, - '50-54': 5.8, - '55-59': 6.5, - '60-64': 6.0, - '65-69': 5.1, - '70-74': 4.1, - '75-79': 2.8, - '80-84': 1.9, - '85+': 1.8}, - 'USA-Oregon': {'0-5': 5.5, - '5-9': 5.7, - '10-14': 6.1, - '15-19': 6.0, - '20-24': 6.3, - '25-29': 7.2, - '30-34': 7.0, - '35-39': 6.9, - '40-44': 6.4, - '45-49': 6.4, - '50-54': 6.0, - '55-59': 6.4, - '60-64': 6.6, - '65-69': 6.2, - '70-74': 4.5, - '75-79': 3.1, - '80-84': 2.0, - '85+': 1.9}, - 'USA-Pennsylvania': {'0-5': 5.5, - '5-9': 5.5, - '10-14': 6.1, - '15-19': 6.4, - '20-24': 6.3, - '25-29': 6.8, - '30-34': 6.5, - '35-39': 6.1, - '40-44': 5.6, - '45-49': 6.3, - '50-54': 6.7, - '55-59': 7.2, - '60-64': 7.0, - '65-69': 5.8, - '70-74': 4.5, - '75-79': 3.3, - '80-84': 2.3, - '85+': 2.4}, - 'USA-Puerto Rico': {'0-5': 3.9, - '5-9': 5.2, - '10-14': 5.7, - '15-19': 6.6, - '20-24': 7.0, - '25-29': 6.5, - '30-34': 5.5, - '35-39': 5.8, - '40-44': 6.6, - '45-49': 6.4, - '50-54': 6.8, - '55-59': 6.7, - '60-64': 6.6, - '65-69': 5.9, - '70-74': 5.5, - '75-79': 4.0, - '80-84': 2.8, - '85+': 2.6}, - 'USA-Rhode Island': {'0-5': 5.1, - '5-9': 5.4, - '10-14': 5.2, - '15-19': 7.1, - '20-24': 7.1, - '25-29': 7.3, - '30-34': 6.6, - '35-39': 6.2, - '40-44': 5.4, - '45-49': 6.3, - '50-54': 7.0, - '55-59': 6.9, - '60-64': 7.1, - '65-69': 5.3, - '70-74': 4.4, - '75-79': 2.9, - '80-84': 2.1, - '85+': 2.5}, - 'USA-South Carolina': {'0-5': 5.7, - '5-9': 6.0, - '10-14': 6.4, - '15-19': 6.7, - '20-24': 6.5, - '25-29': 6.7, - '30-34': 6.2, - '35-39': 6.2, - '40-44': 6.0, - '45-49': 6.2, - '50-54': 6.3, - '55-59': 6.9, - '60-64': 6.5, - '65-69': 6.0, - '70-74': 4.9, - '75-79': 3.2, - '80-84': 1.9, - '85+': 1.7}, - 'USA-South Dakota': {'0-5': 6.8, - '5-9': 6.7, - '10-14': 7.0, - '15-19': 6.8, - '20-24': 6.7, - '25-29': 7.0, - '30-34': 6.2, - '35-39': 6.3, - '40-44': 5.6, - '45-49': 5.3, - '50-54': 5.7, - '55-59': 6.7, - '60-64': 6.7, - '65-69': 5.5, - '70-74': 4.1, - '75-79': 2.7, - '80-84': 1.8, - '85+': 2.5}, - 'USA-Tennessee': {'0-5': 6.0, - '5-9': 6.1, - '10-14': 6.4, - '15-19': 6.5, - '20-24': 6.5, - '25-29': 7.2, - '30-34': 6.4, - '35-39': 6.4, - '40-44': 6.1, - '45-49': 6.6, - '50-54': 6.5, - '55-59': 6.6, - '60-64': 6.6, - '65-69': 5.4, - '70-74': 4.3, - '75-79': 3.0, - '80-84': 1.9, - '85+': 1.7}, - 'USA-Texas': {'0-5': 7.0, - '5-9': 6.9, - '10-14': 7.6, - '15-19': 7.2, - '20-24': 6.9, - '25-29': 7.4, - '30-34': 7.2, - '35-39': 7.1, - '40-44': 6.5, - '45-49': 6.4, - '50-54': 6.0, - '55-59': 5.9, - '60-64': 5.4, - '65-69': 4.3, - '70-74': 3.3, - '75-79': 2.2, - '80-84': 1.4, - '85+': 1.3}, - 'USA-Utah': {'0-5': 7.9, - '5-9': 8.1, - '10-14': 8.6, - '15-19': 7.9, - '20-24': 8.2, - '25-29': 7.8, - '30-34': 6.9, - '35-39': 7.2, - '40-44': 6.7, - '45-49': 5.5, - '50-54': 4.6, - '55-59': 4.8, - '60-64': 4.7, - '65-69': 3.8, - '70-74': 2.9, - '75-79': 1.9, - '80-84': 1.4, - '85+': 1.1}, - 'USA-Vermont': {'0-5': 4.6, - '5-9': 5.1, - '10-14': 5.4, - '15-19': 6.7, - '20-24': 6.9, - '25-29': 6.2, - '30-34': 5.8, - '35-39': 5.9, - '40-44': 5.3, - '45-49': 6.1, - '50-54': 6.8, - '55-59': 7.5, - '60-64': 7.8, - '65-69': 6.9, - '70-74': 5.2, - '75-79': 3.5, - '80-84': 2.1, - '85+': 2.1}, - 'USA-Virginia': {'0-5': 5.9, - '5-9': 6.0, - '10-14': 6.3, - '15-19': 6.6, - '20-24': 6.8, - '25-29': 6.9, - '30-34': 6.9, - '35-39': 6.8, - '40-44': 6.3, - '45-49': 6.5, - '50-54': 6.6, - '55-59': 6.7, - '60-64': 6.2, - '65-69': 5.2, - '70-74': 3.9, - '75-79': 2.8, - '80-84': 1.8, - '85+': 1.7}, - 'USA-Washington': {'0-5': 6.1, - '5-9': 6.2, - '10-14': 6.2, - '15-19': 6.0, - '20-24': 6.3, - '25-29': 7.8, - '30-34': 7.5, - '35-39': 7.2, - '40-44': 6.2, - '45-49': 6.3, - '50-54': 6.1, - '55-59': 6.5, - '60-64': 6.3, - '65-69': 5.3, - '70-74': 4.2, - '75-79': 2.7, - '80-84': 1.6, - '85+': 1.7}, - 'USA-West Virginia': {'0-5': 5.2, - '5-9': 5.4, - '10-14': 5.9, - '15-19': 6.2, - '20-24': 6.3, - '25-29': 6.0, - '30-34': 5.6, - '35-39': 5.9, - '40-44': 6.2, - '45-49': 6.4, - '50-54': 6.5, - '55-59': 7.1, - '60-64': 7.3, - '65-69': 7.1, - '70-74': 4.9, - '75-79': 3.6, - '80-84': 2.3, - '85+': 2.2}, - 'USA-Wisconsin': {'0-5': 5.7, - '5-9': 5.9, - '10-14': 6.4, - '15-19': 6.5, - '20-24': 6.8, - '25-29': 6.4, - '30-34': 6.3, - '35-39': 6.5, - '40-44': 5.7, - '45-49': 6.0, - '50-54': 6.7, - '55-59': 7.2, - '60-64': 7.0, - '65-69': 5.7, - '70-74': 4.2, - '75-79': 2.9, - '80-84': 2.1, - '85+': 2.1}, - 'USA-Wyoming': {'0-5': 6.1, - '5-9': 6.0, - '10-14': 7.0, - '15-19': 7.1, - '20-24': 5.7, - '25-29': 6.7, - '30-34': 6.6, - '35-39': 6.8, - '40-44': 5.7, - '45-49': 5.8, - '50-54': 5.9, - '55-59': 6.6, - '60-64': 7.2, - '65-69': 6.2, - '70-74': 4.1, - '75-79': 3.0, - '80-84': 1.8, - '85+': 1.6} - } - return data +''' +This data is translated from the US Census CSV to JSON/Python format. +''' + +data = { + 'USA-Alabama': {'0-5': 5.9, + '5-9': 5.9, + '10-14': 6.6, + '15-19': 6.8, + '20-24': 6.5, + '25-29': 6.8, + '30-34': 6.2, + '35-39': 6.0, + '40-44': 6.1, + '45-49': 6.3, + '50-54': 6.5, + '55-59': 6.8, + '60-64': 6.5, + '65-69': 5.5, + '70-74': 4.6, + '75-79': 3.1, + '80-84': 2.0, + '85+': 1.7}, + 'USA-Alaska': {'0-5': 7.1, + '5-9': 7.1, + '10-14': 6.7, + '15-19': 6.6, + '20-24': 6.7, + '25-29': 8.5, + '30-34': 7.5, + '35-39': 7.3, + '40-44': 5.9, + '45-49': 5.8, + '50-54': 6.4, + '55-59': 6.4, + '60-64': 6.2, + '65-69': 5.1, + '70-74': 3.0, + '75-79': 1.7, + '80-84': 1.1, + '85+': 1.0}, + 'USA-Arizona': {'0-5': 6.1, + '5-9': 6.2, + '10-14': 6.8, + '15-19': 6.7, + '20-24': 6.8, + '25-29': 7.2, + '30-34': 6.5, + '35-39': 6.3, + '40-44': 6.0, + '45-49': 6.0, + '50-54': 5.8, + '55-59': 6.0, + '60-64': 6.1, + '65-69': 5.5, + '70-74': 4.7, + '75-79': 3.4, + '80-84': 2.1, + '85+': 1.9}, + 'USA-Arkansas': {'0-5': 6.2, + '5-9': 6.4, + '10-14': 6.8, + '15-19': 6.9, + '20-24': 6.6, + '25-29': 6.8, + '30-34': 6.3, + '35-39': 6.3, + '40-44': 5.9, + '45-49': 6.1, + '50-54': 6.2, + '55-59': 6.5, + '60-64': 6.2, + '65-69': 5.4, + '70-74': 4.5, + '75-79': 3.2, + '80-84': 1.9, + '85+': 1.9}, + 'USA-California': {'0-5': 6.1, + '5-9': 6.1, + '10-14': 6.7, + '15-19': 6.5, + '20-24': 6.9, + '25-29': 7.9, + '30-34': 7.4, + '35-39': 7.0, + '40-44': 6.3, + '45-49': 6.5, + '50-54': 6.3, + '55-59': 6.3, + '60-64': 5.8, + '65-69': 4.7, + '70-74': 3.6, + '75-79': 2.5, + '80-84': 1.7, + '85+': 1.8}, + 'USA-Colorado': {'0-5': 5.9, + '5-9': 6.2, + '10-14': 6.4, + '15-19': 6.5, + '20-24': 6.6, + '25-29': 7.9, + '30-34': 7.8, + '35-39': 7.1, + '40-44': 6.6, + '45-49': 6.5, + '50-54': 6.0, + '55-59': 6.4, + '60-64': 6.1, + '65-69': 5.0, + '70-74': 3.8, + '75-79': 2.3, + '80-84': 1.5, + '85+': 1.5}, + 'USA-Connecticut': {'0-5': 5.1, + '5-9': 5.4, + '10-14': 6.3, + '15-19': 6.8, + '20-24': 6.7, + '25-29': 6.2, + '30-34': 6.3, + '35-39': 6.0, + '40-44': 5.9, + '45-49': 6.6, + '50-54': 7.3, + '55-59': 7.3, + '60-64': 7.1, + '65-69': 5.2, + '70-74': 4.4, + '75-79': 3.1, + '80-84': 2.0, + '85+': 2.5}, + 'USA-Delaware': {'0-5': 5.6, + '5-9': 5.4, + '10-14': 6.5, + '15-19': 6.1, + '20-24': 6.2, + '25-29': 6.8, + '30-34': 6.3, + '35-39': 6.1, + '40-44': 5.5, + '45-49': 6.0, + '50-54': 6.7, + '55-59': 7.1, + '60-64': 7.0, + '65-69': 6.2, + '70-74': 5.0, + '75-79': 3.8, + '80-84': 1.8, + '85+': 1.9}, + 'USA-District of Columbia': {'0-5': 6.5, + '5-9': 4.7, + '10-14': 4.8, + '15-19': 5.3, + '20-24': 7.5, + '25-29': 11.7, + '30-34': 11.5, + '35-39': 9.0, + '40-44': 6.0, + '45-49': 5.6, + '50-54': 5.2, + '55-59': 5.2, + '60-64': 4.7, + '65-69': 3.7, + '70-74': 3.3, + '75-79': 2.3, + '80-84': 1.4, + '85+': 1.6}, + 'USA-Florida': {'0-5': 5.3, + '5-9': 5.3, + '10-14': 5.8, + '15-19': 5.8, + '20-24': 5.9, + '25-29': 6.7, + '30-34': 6.3, + '35-39': 6.2, + '40-44': 5.9, + '45-49': 6.3, + '50-54': 6.5, + '55-59': 6.8, + '60-64': 6.6, + '65-69': 6.1, + '70-74': 5.2, + '75-79': 3.9, + '80-84': 2.6, + '85+': 2.6}, + 'USA-Georgia': {'0-5': 6.1, + '5-9': 6.5, + '10-14': 7.0, + '15-19': 7.2, + '20-24': 6.8, + '25-29': 7.1, + '30-34': 6.6, + '35-39': 6.8, + '40-44': 6.5, + '45-49': 6.8, + '50-54': 6.5, + '55-59': 6.3, + '60-64': 5.8, + '65-69': 4.7, + '70-74': 3.8, + '75-79': 2.5, + '80-84': 1.5, + '85+': 1.4}, + 'USA-Hawaii': {'0-5': 6.2, + '5-9': 5.9, + '10-14': 6.0, + '15-19': 5.5, + '20-24': 6.4, + '25-29': 7.3, + '30-34': 6.9, + '35-39': 6.7, + '40-44': 6.1, + '45-49': 6.0, + '50-54': 6.0, + '55-59': 6.1, + '60-64': 6.6, + '65-69': 6.0, + '70-74': 4.6, + '75-79': 2.9, + '80-84': 2.2, + '85+': 2.8}, + 'USA-Idaho': {'0-5': 6.5, + '5-9': 7.1, + '10-14': 7.4, + '15-19': 7.2, + '20-24': 6.6, + '25-29': 6.7, + '30-34': 6.3, + '35-39': 6.3, + '40-44': 6.2, + '45-49': 5.9, + '50-54': 5.6, + '55-59': 6.4, + '60-64': 5.9, + '65-69': 5.5, + '70-74': 4.1, + '75-79': 3.0, + '80-84': 1.6, + '85+': 1.7}, + 'USA-Illinois': {'0-5': 6.0, + '5-9': 6.0, + '10-14': 6.6, + '15-19': 6.6, + '20-24': 6.6, + '25-29': 7.1, + '30-34': 6.8, + '35-39': 6.6, + '40-44': 6.3, + '45-49': 6.4, + '50-54': 6.4, + '55-59': 6.7, + '60-64': 6.4, + '65-69': 5.0, + '70-74': 3.9, + '75-79': 2.8, + '80-84': 1.8, + '85+': 2.0}, + 'USA-Indiana': {'0-5': 6.2, + '5-9': 6.4, + '10-14': 6.7, + '15-19': 6.9, + '20-24': 7.0, + '25-29': 6.8, + '30-34': 6.2, + '35-39': 6.5, + '40-44': 5.8, + '45-49': 6.2, + '50-54': 6.3, + '55-59': 6.7, + '60-64': 6.4, + '65-69': 5.2, + '70-74': 3.9, + '75-79': 2.8, + '80-84': 1.8, + '85+': 1.9}, + 'USA-Iowa': {'0-5': 6.3, + '5-9': 6.3, + '10-14': 6.8, + '15-19': 7.0, + '20-24': 7.0, + '25-29': 6.4, + '30-34': 6.1, + '35-39': 6.6, + '40-44': 5.5, + '45-49': 5.8, + '50-54': 5.9, + '55-59': 6.8, + '60-64': 6.5, + '65-69': 5.4, + '70-74': 4.1, + '75-79': 3.0, + '80-84': 2.2, + '85+': 2.4}, + 'USA-Kansas': {'0-5': 6.4, + '5-9': 6.5, + '10-14': 7.2, + '15-19': 7.0, + '20-24': 7.2, + '25-29': 6.6, + '30-34': 6.3, + '35-39': 6.4, + '40-44': 5.9, + '45-49': 5.8, + '50-54': 5.9, + '55-59': 6.5, + '60-64': 6.3, + '65-69': 5.4, + '70-74': 3.7, + '75-79': 2.7, + '80-84': 1.9, + '85+': 2.2}, + 'USA-Kentucky': {'0-5': 6.1, + '5-9': 6.3, + '10-14': 6.4, + '15-19': 6.5, + '20-24': 6.7, + '25-29': 6.9, + '30-34': 6.1, + '35-39': 6.3, + '40-44': 6.1, + '45-49': 6.4, + '50-54': 6.5, + '55-59': 6.8, + '60-64': 6.6, + '65-69': 5.5, + '70-74': 4.3, + '75-79': 2.9, + '80-84': 2.0, + '85+': 1.8}, + 'USA-Louisiana': {'0-5': 6.5, + '5-9': 6.4, + '10-14': 6.8, + '15-19': 6.6, + '20-24': 6.6, + '25-29': 7.1, + '30-34': 6.8, + '35-39': 6.8, + '40-44': 5.8, + '45-49': 6.0, + '50-54': 6.2, + '55-59': 6.5, + '60-64': 6.4, + '65-69': 5.4, + '70-74': 3.9, + '75-79': 2.8, + '80-84': 1.8, + '85+': 1.6}, + 'USA-Maine': {'0-5': 4.7, + '5-9': 5.1, + '10-14': 5.4, + '15-19': 5.8, + '20-24': 5.5, + '25-29': 6.0, + '30-34': 6.0, + '35-39': 6.0, + '40-44': 5.5, + '45-49': 6.3, + '50-54': 7.1, + '55-59': 7.9, + '60-64': 8.1, + '65-69': 6.9, + '70-74': 5.3, + '75-79': 3.4, + '80-84': 2.3, + '85+': 2.6}, + 'USA-Maryland': {'0-5': 6.0, + '5-9': 6.0, + '10-14': 6.4, + '15-19': 6.3, + '20-24': 6.4, + '25-29': 6.9, + '30-34': 6.8, + '35-39': 6.8, + '40-44': 6.0, + '45-49': 6.6, + '50-54': 7.0, + '55-59': 6.9, + '60-64': 6.5, + '65-69': 5.0, + '70-74': 4.0, + '75-79': 2.8, + '80-84': 1.8, + '85+': 1.8}, + 'USA-Massachusetts': {'0-5': 5.2, + '5-9': 5.4, + '10-14': 5.7, + '15-19': 6.6, + '20-24': 7.1, + '25-29': 7.3, + '30-34': 7.0, + '35-39': 6.3, + '40-44': 5.9, + '45-49': 6.4, + '50-54': 6.9, + '55-59': 7.1, + '60-64': 6.5, + '65-69': 5.3, + '70-74': 4.2, + '75-79': 2.8, + '80-84': 1.9, + '85+': 2.2}, + 'USA-Michigan': {'0-5': 5.7, + '5-9': 5.9, + '10-14': 6.2, + '15-19': 6.6, + '20-24': 6.9, + '25-29': 6.9, + '30-34': 6.0, + '35-39': 6.0, + '40-44': 5.6, + '45-49': 6.3, + '50-54': 6.6, + '55-59': 7.0, + '60-64': 7.0, + '65-69': 5.7, + '70-74': 4.4, + '75-79': 3.1, + '80-84': 2.0, + '85+': 2.0}, + 'USA-Minnesota': {'0-5': 6.3, + '5-9': 6.4, + '10-14': 6.6, + '15-19': 6.4, + '20-24': 6.4, + '25-29': 6.7, + '30-34': 6.8, + '35-39': 6.8, + '40-44': 5.9, + '45-49': 6.0, + '50-54': 6.3, + '55-59': 7.1, + '60-64': 6.3, + '65-69': 5.3, + '70-74': 3.8, + '75-79': 2.8, + '80-84': 1.9, + '85+': 2.1}, + 'USA-Mississippi': {'0-5': 6.0, + '5-9': 6.4, + '10-14': 7.2, + '15-19': 7.3, + '20-24': 6.9, + '25-29': 6.6, + '30-34': 6.0, + '35-39': 6.7, + '40-44': 6.0, + '45-49': 6.0, + '50-54': 6.1, + '55-59': 6.4, + '60-64': 6.5, + '65-69': 5.2, + '70-74': 4.3, + '75-79': 3.0, + '80-84': 1.8, + '85+': 1.6}, + 'USA-Missouri': {'0-5': 6.0, + '5-9': 6.1, + '10-14': 6.5, + '15-19': 6.4, + '20-24': 6.6, + '25-29': 6.9, + '30-34': 6.5, + '35-39': 6.4, + '40-44': 5.7, + '45-49': 6.0, + '50-54': 6.2, + '55-59': 6.8, + '60-64': 6.7, + '65-69': 5.3, + '70-74': 4.4, + '75-79': 3.1, + '80-84': 2.0, + '85+': 2.0}, + 'USA-Montana': {'0-5': 5.8, + '5-9': 5.8, + '10-14': 6.4, + '15-19': 6.3, + '20-24': 6.4, + '25-29': 6.5, + '30-34': 6.1, + '35-39': 6.5, + '40-44': 5.6, + '45-49': 5.6, + '50-54': 5.8, + '55-59': 6.8, + '60-64': 7.5, + '65-69': 6.5, + '70-74': 4.9, + '75-79': 3.5, + '80-84': 2.0, + '85+': 2.0}, + 'USA-Nebraska': {'0-5': 6.8, + '5-9': 6.7, + '10-14': 7.1, + '15-19': 6.9, + '20-24': 6.9, + '25-29': 6.6, + '30-34': 6.7, + '35-39': 6.8, + '40-44': 5.8, + '45-49': 5.7, + '50-54': 5.6, + '55-59': 6.4, + '60-64': 6.2, + '65-69': 5.3, + '70-74': 3.7, + '75-79': 2.6, + '80-84': 2.0, + '85+': 2.2}, + 'USA-Nevada': {'0-5': 6.1, + '5-9': 6.2, + '10-14': 6.6, + '15-19': 6.0, + '20-24': 5.9, + '25-29': 7.4, + '30-34': 7.1, + '35-39': 6.8, + '40-44': 6.5, + '45-49': 6.7, + '50-54': 6.4, + '55-59': 6.3, + '60-64': 6.1, + '65-69': 5.2, + '70-74': 4.4, + '75-79': 2.8, + '80-84': 1.7, + '85+': 1.5}, + 'USA-New Hampshire': {'0-5': 4.6, + '5-9': 5.1, + '10-14': 5.7, + '15-19': 6.8, + '20-24': 6.3, + '25-29': 6.3, + '30-34': 6.1, + '35-39': 5.9, + '40-44': 5.6, + '45-49': 6.6, + '50-54': 7.4, + '55-59': 8.2, + '60-64': 7.5, + '65-69': 6.1, + '70-74': 4.7, + '75-79': 3.1, + '80-84': 1.9, + '85+': 2.3}, + 'USA-New Jersey': {'0-5': 5.8, + '5-9': 5.8, + '10-14': 6.4, + '15-19': 6.2, + '20-24': 6.2, + '25-29': 6.5, + '30-34': 6.4, + '35-39': 6.6, + '40-44': 6.3, + '45-49': 6.7, + '50-54': 7.1, + '55-59': 7.1, + '60-64': 6.6, + '65-69': 5.1, + '70-74': 4.1, + '75-79': 2.9, + '80-84': 1.9, + '85+': 2.2}, + 'USA-New Mexico': {'0-5': 5.7, + '5-9': 6.1, + '10-14': 7.2, + '15-19': 6.8, + '20-24': 6.6, + '25-29': 6.7, + '30-34': 6.6, + '35-39': 6.5, + '40-44': 5.7, + '45-49': 5.7, + '50-54': 5.8, + '55-59': 6.5, + '60-64': 6.5, + '65-69': 5.8, + '70-74': 4.7, + '75-79': 3.1, + '80-84': 2.0, + '85+': 1.9}, + 'USA-New York': {'0-5': 5.8, + '5-9': 5.5, + '10-14': 5.9, + '15-19': 6.2, + '20-24': 6.6, + '25-29': 7.6, + '30-34': 7.1, + '35-39': 6.5, + '40-44': 6.0, + '45-49': 6.3, + '50-54': 6.8, + '55-59': 6.8, + '60-64': 6.5, + '65-69': 5.1, + '70-74': 4.2, + '75-79': 2.9, + '80-84': 2.0, + '85+': 2.2}, + 'USA-North Carolina': {'0-5': 5.8, + '5-9': 6.0, + '10-14': 6.5, + '15-19': 6.8, + '20-24': 6.6, + '25-29': 6.9, + '30-34': 6.4, + '35-39': 6.4, + '40-44': 6.2, + '45-49': 6.7, + '50-54': 6.6, + '55-59': 6.5, + '60-64': 6.4, + '65-69': 5.4, + '70-74': 4.4, + '75-79': 3.0, + '80-84': 1.8, + '85+': 1.7}, + 'USA-North Dakota': {'0-5': 6.9, + '5-9': 6.7, + '10-14': 6.2, + '15-19': 6.1, + '20-24': 8.2, + '25-29': 8.1, + '30-34': 7.3, + '35-39': 6.6, + '40-44': 5.3, + '45-49': 5.3, + '50-54': 5.4, + '55-59': 6.5, + '60-64': 6.0, + '65-69': 5.0, + '70-74': 3.5, + '75-79': 2.5, + '80-84': 2.0, + '85+': 2.4}, + 'USA-Ohio': {'0-5': 5.9, + '5-9': 5.9, + '10-14': 6.4, + '15-19': 6.6, + '20-24': 6.4, + '25-29': 6.8, + '30-34': 6.3, + '35-39': 6.2, + '40-44': 5.8, + '45-49': 6.3, + '50-54': 6.5, + '55-59': 7.0, + '60-64': 6.8, + '65-69': 5.6, + '70-74': 4.2, + '75-79': 3.1, + '80-84': 2.0, + '85+': 2.1}, + 'USA-Oklahoma': {'0-5': 6.5, + '5-9': 6.6, + '10-14': 7.1, + '15-19': 6.9, + '20-24': 6.8, + '25-29': 7.1, + '30-34': 6.6, + '35-39': 6.6, + '40-44': 5.8, + '45-49': 5.9, + '50-54': 5.8, + '55-59': 6.5, + '60-64': 6.0, + '65-69': 5.1, + '70-74': 4.1, + '75-79': 2.8, + '80-84': 1.9, + '85+': 1.8}, + 'USA-Oregon': {'0-5': 5.5, + '5-9': 5.7, + '10-14': 6.1, + '15-19': 6.0, + '20-24': 6.3, + '25-29': 7.2, + '30-34': 7.0, + '35-39': 6.9, + '40-44': 6.4, + '45-49': 6.4, + '50-54': 6.0, + '55-59': 6.4, + '60-64': 6.6, + '65-69': 6.2, + '70-74': 4.5, + '75-79': 3.1, + '80-84': 2.0, + '85+': 1.9}, + 'USA-Pennsylvania': {'0-5': 5.5, + '5-9': 5.5, + '10-14': 6.1, + '15-19': 6.4, + '20-24': 6.3, + '25-29': 6.8, + '30-34': 6.5, + '35-39': 6.1, + '40-44': 5.6, + '45-49': 6.3, + '50-54': 6.7, + '55-59': 7.2, + '60-64': 7.0, + '65-69': 5.8, + '70-74': 4.5, + '75-79': 3.3, + '80-84': 2.3, + '85+': 2.4}, + 'USA-Puerto Rico': {'0-5': 3.9, + '5-9': 5.2, + '10-14': 5.7, + '15-19': 6.6, + '20-24': 7.0, + '25-29': 6.5, + '30-34': 5.5, + '35-39': 5.8, + '40-44': 6.6, + '45-49': 6.4, + '50-54': 6.8, + '55-59': 6.7, + '60-64': 6.6, + '65-69': 5.9, + '70-74': 5.5, + '75-79': 4.0, + '80-84': 2.8, + '85+': 2.6}, + 'USA-Rhode Island': {'0-5': 5.1, + '5-9': 5.4, + '10-14': 5.2, + '15-19': 7.1, + '20-24': 7.1, + '25-29': 7.3, + '30-34': 6.6, + '35-39': 6.2, + '40-44': 5.4, + '45-49': 6.3, + '50-54': 7.0, + '55-59': 6.9, + '60-64': 7.1, + '65-69': 5.3, + '70-74': 4.4, + '75-79': 2.9, + '80-84': 2.1, + '85+': 2.5}, + 'USA-South Carolina': {'0-5': 5.7, + '5-9': 6.0, + '10-14': 6.4, + '15-19': 6.7, + '20-24': 6.5, + '25-29': 6.7, + '30-34': 6.2, + '35-39': 6.2, + '40-44': 6.0, + '45-49': 6.2, + '50-54': 6.3, + '55-59': 6.9, + '60-64': 6.5, + '65-69': 6.0, + '70-74': 4.9, + '75-79': 3.2, + '80-84': 1.9, + '85+': 1.7}, + 'USA-South Dakota': {'0-5': 6.8, + '5-9': 6.7, + '10-14': 7.0, + '15-19': 6.8, + '20-24': 6.7, + '25-29': 7.0, + '30-34': 6.2, + '35-39': 6.3, + '40-44': 5.6, + '45-49': 5.3, + '50-54': 5.7, + '55-59': 6.7, + '60-64': 6.7, + '65-69': 5.5, + '70-74': 4.1, + '75-79': 2.7, + '80-84': 1.8, + '85+': 2.5}, + 'USA-Tennessee': {'0-5': 6.0, + '5-9': 6.1, + '10-14': 6.4, + '15-19': 6.5, + '20-24': 6.5, + '25-29': 7.2, + '30-34': 6.4, + '35-39': 6.4, + '40-44': 6.1, + '45-49': 6.6, + '50-54': 6.5, + '55-59': 6.6, + '60-64': 6.6, + '65-69': 5.4, + '70-74': 4.3, + '75-79': 3.0, + '80-84': 1.9, + '85+': 1.7}, + 'USA-Texas': {'0-5': 7.0, + '5-9': 6.9, + '10-14': 7.6, + '15-19': 7.2, + '20-24': 6.9, + '25-29': 7.4, + '30-34': 7.2, + '35-39': 7.1, + '40-44': 6.5, + '45-49': 6.4, + '50-54': 6.0, + '55-59': 5.9, + '60-64': 5.4, + '65-69': 4.3, + '70-74': 3.3, + '75-79': 2.2, + '80-84': 1.4, + '85+': 1.3}, + 'USA-Utah': {'0-5': 7.9, + '5-9': 8.1, + '10-14': 8.6, + '15-19': 7.9, + '20-24': 8.2, + '25-29': 7.8, + '30-34': 6.9, + '35-39': 7.2, + '40-44': 6.7, + '45-49': 5.5, + '50-54': 4.6, + '55-59': 4.8, + '60-64': 4.7, + '65-69': 3.8, + '70-74': 2.9, + '75-79': 1.9, + '80-84': 1.4, + '85+': 1.1}, + 'USA-Vermont': {'0-5': 4.6, + '5-9': 5.1, + '10-14': 5.4, + '15-19': 6.7, + '20-24': 6.9, + '25-29': 6.2, + '30-34': 5.8, + '35-39': 5.9, + '40-44': 5.3, + '45-49': 6.1, + '50-54': 6.8, + '55-59': 7.5, + '60-64': 7.8, + '65-69': 6.9, + '70-74': 5.2, + '75-79': 3.5, + '80-84': 2.1, + '85+': 2.1}, + 'USA-Virginia': {'0-5': 5.9, + '5-9': 6.0, + '10-14': 6.3, + '15-19': 6.6, + '20-24': 6.8, + '25-29': 6.9, + '30-34': 6.9, + '35-39': 6.8, + '40-44': 6.3, + '45-49': 6.5, + '50-54': 6.6, + '55-59': 6.7, + '60-64': 6.2, + '65-69': 5.2, + '70-74': 3.9, + '75-79': 2.8, + '80-84': 1.8, + '85+': 1.7}, + 'USA-Washington': {'0-5': 6.1, + '5-9': 6.2, + '10-14': 6.2, + '15-19': 6.0, + '20-24': 6.3, + '25-29': 7.8, + '30-34': 7.5, + '35-39': 7.2, + '40-44': 6.2, + '45-49': 6.3, + '50-54': 6.1, + '55-59': 6.5, + '60-64': 6.3, + '65-69': 5.3, + '70-74': 4.2, + '75-79': 2.7, + '80-84': 1.6, + '85+': 1.7}, + 'USA-West Virginia': {'0-5': 5.2, + '5-9': 5.4, + '10-14': 5.9, + '15-19': 6.2, + '20-24': 6.3, + '25-29': 6.0, + '30-34': 5.6, + '35-39': 5.9, + '40-44': 6.2, + '45-49': 6.4, + '50-54': 6.5, + '55-59': 7.1, + '60-64': 7.3, + '65-69': 7.1, + '70-74': 4.9, + '75-79': 3.6, + '80-84': 2.3, + '85+': 2.2}, + 'USA-Wisconsin': {'0-5': 5.7, + '5-9': 5.9, + '10-14': 6.4, + '15-19': 6.5, + '20-24': 6.8, + '25-29': 6.4, + '30-34': 6.3, + '35-39': 6.5, + '40-44': 5.7, + '45-49': 6.0, + '50-54': 6.7, + '55-59': 7.2, + '60-64': 7.0, + '65-69': 5.7, + '70-74': 4.2, + '75-79': 2.9, + '80-84': 2.1, + '85+': 2.1}, + 'USA-Wyoming': {'0-5': 6.1, + '5-9': 6.0, + '10-14': 7.0, + '15-19': 7.1, + '20-24': 5.7, + '25-29': 6.7, + '30-34': 6.6, + '35-39': 6.8, + '40-44': 5.7, + '45-49': 5.8, + '50-54': 5.9, + '55-59': 6.6, + '60-64': 7.2, + '65-69': 6.2, + '70-74': 4.1, + '75-79': 3.0, + '80-84': 1.8, + '85+': 1.6} +} diff --git a/covasim/misc.py b/covasim/misc.py index a1ca673d7..e0548275d 100644 --- a/covasim/misc.py +++ b/covasim/misc.py @@ -8,7 +8,7 @@ import pylab as pl import sciris as sc import scipy.stats as sps -from . import version as cvver +from . import version as cvv #%% Convenience imports from Sciris @@ -113,7 +113,7 @@ def load(*args, do_migrate=True, **kwargs): ''' obj = sc.loadobj(*args, **kwargs) if hasattr(obj, 'version'): - v_curr = cvver.__version__ + v_curr = cvv.__version__ v_obj = obj.version cmp = check_version(v_obj, verbose=False) if cmp != 0: @@ -146,14 +146,19 @@ def save(*args, **kwargs): return filepath -def migrate(obj, verbose=True, die=False): +def migrate(obj, update=True, verbose=True, die=False): ''' Define migrations allowing compatibility between different versions of saved files. Usually invoked automatically upon load, but can be called directly by the user to load custom objects, e.g. lists of sims. + Currently supported objects are sims, multisims, scenarios, and people. + Args: - obj (any): the object to migrate (must be a Sim or MultiSim) + obj (any): the object to migrate + update (bool): whether to update version information to current version after successful migration + verbose (bool): whether to print warnings if something goes wrong + die (bool): whether to raise an exception if something goes wrong Returns: The migrated object @@ -163,25 +168,28 @@ def migrate(obj, verbose=True, die=False): sims = cv.load('my-list-of-sims.obj') sims = [cv.migrate(sim) for sim in sims] ''' - from .base import BaseSim # Import here to avoid recursion - from .run import MultiSim - from .interventions import test_prob - - if not hasattr(obj, 'version'): - errormsg = f'Object {obj} does not have a "version" attribute; cannot be migrated' - raise ValueError(errormsg) + from . import base as cvb + from . import run as cvr + from . import interventions as cvi # Migrations for simulations - if isinstance(obj, BaseSim): + if isinstance(obj, cvb.BaseSim): sim = obj + + # Migration from <2.0.0 to 2.0.0 if sc.compareversions(sim.version, '2.0.0') == -1: # Migrate from <2.0 to 2.0 + if verbose: print(f'Migrating sim from version {sim.version} to version {cvv.__version__}') # Add missing attribute if not hasattr(sim, '_default_ver'): sim._default_ver = None + # Recursively migrate people if needed + if sim.people: + sim.people = migrate(sim.people, update=update) + # Rename intervention attribute - tps = sim.get_interventions(test_prob) + tps = sim.get_interventions(cvi.test_prob) for tp in tps: try: tp.sensitivity = tp.test_sensitivity @@ -189,18 +197,44 @@ def migrate(obj, verbose=True, die=False): except: pass + # Migrations for People + elif isinstance(obj, cvb.BasePeople): + ppl = obj + if not hasattr(ppl, 'version'): # For people prior to 2.0 + if verbose: print(f'Migrating people from version <2.0 to version {cvv.__version__}') + cvb.set_metadata(ppl) # Set all metadata + # Migrations for MultiSims -- use recursion - elif isinstance(obj, MultiSim): + elif isinstance(obj, cvr.MultiSim): msim = obj - msim.base_sim = migrate(msim.base_sim) - msim.sims = [migrate(sim) for sim in msim.sims] - - # Otherwise + msim.base_sim = migrate(msim.base_sim, update=update) + msim.sims = [migrate(sim, update=update) for sim in msim.sims] + if not hasattr(msim, 'version'): # For msims prior to 2.0 + if verbose: print(f'Migrating multisim from version <2.0 to version {cvv.__version__}') + cvb.set_metadata(msim) # Set all metadata + msim.label = None + + # Migrations for Scenarios + elif isinstance(obj, cvr.Scenarios): + scens = obj + scens.base_sim = migrate(scens.base_sim, update=update) + for key,simlist in scens.sims.items(): + scens.sims[key] = [migrate(sim, update=update) for sim in simlist] # Nested loop + if not hasattr(scens, 'version'): # For scenarios prior to 2.0 + if verbose: print(f'Migrating scenarios from version <2.0 to version {cvv.__version__}') + cvb.set_metadata(scens) # Set all metadata + scens.label = None + + # Unreconized object type else: - errormsg = f'Object {obj} does have a version attribute, but type {type(obj)} cannot be migrated' + errormsg = f'Object {obj} of type {type(obj)} is not understood and cannot be migrated: must be a sim, multisim, scenario, or people object' if verbose: print(errormsg) elif die: raise TypeError(errormsg) + # If requested, update the stored version to the current version + if update: + obj.version = cvv.__version__ + return obj @@ -232,7 +266,7 @@ def savefig(filename=None, comments=None, **kwargs): filename = f'covasim_{now}.png' metadata = {} - metadata['Covasim version'] = cvver.__version__ + metadata['Covasim version'] = cvv.__version__ gitinfo = git_info() for key,value in gitinfo['covasim'].items(): metadata[f'Covasim {key}'] = value @@ -289,7 +323,7 @@ def git_info(filename=None, check=False, comments=None, old_info=None, die=False # Get git info calling_file = sc.makefilepath(sc.getcaller(frame=frame, tostring=False)['filename']) - cv_info = {'version':cvver.__version__} + cv_info = {'version':cvv.__version__} cv_info.update(sc.gitinfo(__file__, verbose=False)) caller_info = sc.gitinfo(calling_file, verbose=False) caller_info['filename'] = calling_file @@ -342,7 +376,7 @@ def check_version(expected, die=False, verbose=True): else: valid = 0 # Assume == is the only valid comparison expected = expected.lstrip('<=>') # Remove comparator information - version = cvver.__version__ + version = cvv.__version__ compare = sc.compareversions(version, expected) # Returns -1, 0, or 1 relation = ['older', '', 'newer'][compare+1] # Picks the right string if relation: # Versions mismatch, print warning or raise error diff --git a/covasim/people.py b/covasim/people.py index d4f70cdb4..c08637e34 100644 --- a/covasim/people.py +++ b/covasim/people.py @@ -6,6 +6,7 @@ import numpy as np import sciris as sc from collections import defaultdict +from . import version as cvv from . import utils as cvu from . import defaults as cvd from . import base as cvb @@ -42,6 +43,8 @@ def __init__(self, pars, strict=True, **kwargs): pars = {'pop_size':pars} # Ensure it's a dictionary self.pars = pars # Equivalent to self.set_pars(pars) self.pop_size = int(pars['pop_size']) + self.location = pars.get('location') # Try to get location, but set to None otherwise + self.version = cvv.__version__ # Store version info # Other initialization self.t = 0 # Keep current simulation time diff --git a/covasim/run.py b/covasim/run.py index d8f4d6b28..4554160cc 100644 --- a/covasim/run.py +++ b/covasim/run.py @@ -33,7 +33,7 @@ def make_metapars(): return metapars -class MultiSim(sc.prettyobj): +class MultiSim(cvb.FlexPretty): ''' Class for running multiple copies of a simulation. The parameter n_runs controls how many copies of the simulation there will be, if a list of sims @@ -43,6 +43,7 @@ class MultiSim(sc.prettyobj): Args: sims (Sim/list) : a single sim or a list of sims base_sim (Sim) : the sim used for shared properties; if not supplied, the first of the sims provided + label (str) : the name of the multisim initialize (bool) : whether or not to initialize the sims (otherwise, initialize them during run) kwargs (dict) : stored in run_args and passed to run() @@ -69,7 +70,7 @@ class MultiSim(sc.prettyobj): msim.plot() # Plot as single sim ''' - def __init__(self, sims=None, base_sim=None, initialize=False, **kwargs): + def __init__(self, sims=None, base_sim=None, label=None, initialize=False, **kwargs): # Handle inputs if base_sim is None: @@ -85,9 +86,11 @@ def __init__(self, sims=None, base_sim=None, initialize=False, **kwargs): # Set properties self.sims = sims self.base_sim = base_sim + self.label = label self.run_args = sc.mergedicts(kwargs) self.results = None self.which = None # Whether the multisim is to be reduced, combined, etc. + cvb.set_metadata(self) # Set version, date, and git info # Optionally initialize if initialize: @@ -208,6 +211,13 @@ def reduce(self, quantiles=None, use_mean=False, bounds=None, output=False): use_mean (bool): whether to use the mean instead of the median bounds (float): if use_mean=True, the multiplier on the standard deviation for upper and lower bounds (default 2) output (bool): whether to return the "reduced" sim (in any case, modify the multisim in-place) + + **Example**:: + + msim = cv.MultiSim(cv.Sim()) + msim.run() + msim.reduce() + msim.summarize() ''' if use_mean: @@ -253,7 +263,7 @@ def reduce(self, quantiles=None, use_mean=False, bounds=None, output=False): reduced_sim.results[reskey].high = np.quantile(raw[reskey], q=quantiles['high'], axis=1) # Compute and store final results - reduced_sim.summarize(verbose=False, update=True) + reduced_sim.compute_summary() self.orig_base_sim = self.base_sim self.base_sim = reduced_sim self.results = reduced_sim.results @@ -268,7 +278,7 @@ def reduce(self, quantiles=None, use_mean=False, bounds=None, output=False): def mean(self, bounds=None, **kwargs): ''' - Alias for reduce(use_mean=True). + Alias for reduce(use_mean=True). See reduce() for full description. Args: bounds (float): multiplier on the standard deviation for the upper and lower bounds (default, 2) @@ -279,7 +289,7 @@ def mean(self, bounds=None, **kwargs): def median(self, quantiles=None, **kwargs): ''' - Alias for reduce(use_mean=False). + Alias for reduce(use_mean=False). See reduce() for full description. Args: quantiles (list or dict): upper and lower quantiles (default, 0.1 and 0.9) @@ -289,7 +299,16 @@ def median(self, quantiles=None, **kwargs): def combine(self, output=False): - ''' Combine multiple sims into a single sim with scaled results ''' + ''' + Combine multiple sims into a single sim with scaled results. + + **Example**:: + + msim = cv.MultiSim(cv.Sim()) + msim.run() + msim.combine() + msim.summarize() + ''' n_runs = len(self) combined_sim = sc.dcp(self.sims[0]) @@ -312,7 +331,7 @@ def combine(self, output=False): combined_sim.results[key].values /= n_runs # Compute and store final results - combined_sim.summarize(verbose=False, update=True) + combined_sim.compute_summary() self.orig_base_sim = self.base_sim self.base_sim = combined_sim self.results = combined_sim.results @@ -326,13 +345,13 @@ def combine(self, output=False): return - def compare(self, t=-1, sim_inds=None, output=False, do_plot=False, **kwargs): + def compare(self, t=None, sim_inds=None, output=False, do_plot=False, **kwargs): ''' Create a dataframe compare sims at a single point in time. Args: t (int/str) : the day (or date) to do the comparison; default, the end - sim_inds (list) : list of integers of which sims to include (default : all) + sim_inds (list) : list of integers of which sims to include (default: all) output (bool) : whether or not to return the comparison as a dataframe do_plot (bool) : whether or not to plot the comparison (see also plot_compare()) kwargs (dict) : passed to plot_compare() @@ -341,6 +360,13 @@ def compare(self, t=-1, sim_inds=None, output=False, do_plot=False, **kwargs): df (dataframe): a dataframe comparison ''' + # Handle time + if t is None: + t = -1 + daystr = 'the last day' + else: + daystr = f'day {t}' + # Handle the indices if sim_inds is None: sim_inds = list(range(len(self.sims))) @@ -349,13 +375,14 @@ def compare(self, t=-1, sim_inds=None, output=False, do_plot=False, **kwargs): resdict = defaultdict(dict) for i,s in enumerate(sim_inds): sim = self.sims[s] + day = sim.day(t) # Unlikely, but different sims might have different start days label = sim.label if not label: # Give it a label if it doesn't have one label = f'Sim {i}' if label in resdict: # Avoid duplicates label += f' ({i})' for reskey in sim.result_keys(): - val = sim.results[reskey].values[t] + val = sim.results[reskey].values[day] if reskey not in ['r_eff', 'doubling_time']: val = int(val) resdict[label][reskey] = val @@ -364,11 +391,11 @@ def compare(self, t=-1, sim_inds=None, output=False, do_plot=False, **kwargs): self.plot_compare(**kwargs) df = pd.DataFrame.from_dict(resdict).astype(object) # astype is necessary to prevent type coercion - if output: - return df - else: + if not output: + print(f'Results for {daystr} in each sim:') print(df) - return None + else: + return df def plot(self, to_plot=None, inds=None, plot_sims=False, color_by_sim=None, max_sims=5, colors=None, labels=None, alpha_range=None, plot_args=None, show_args=None, **kwargs): @@ -695,27 +722,90 @@ def split(self, inds=None, chunks=None): return mlist + def disp(self, output=False): + ''' + Display a verbose description of a multisim. See also multisim.summarize() + (medium length output) and multisim.brief() (short output). + + Args: + output (bool): if true, return a string instead of printing output + + **Example**:: + + msim = cv.MultiSim(cv.Sim(verbose=0), label='Example multisim') + msim.run() + msim.disp() # Displays detailed output + ''' + string = self._disp() + if not output: + print(string) + else: + return string + + def summarize(self, output=False): - ''' Print a brief summary of the MultiSim ''' - string = 'MultiSim summary:\n' - string += f' Number of sims: {len(self.sims)}\n' + ''' + Print a moderate length summary of the MultiSim. See also multisim.disp() + (detailed output) and multisim.brief() (short output). + + Args: + output (bool): if true, return a string instead of printing output + + **Example**:: + + msim = cv.MultiSim(cv.Sim(verbose=0), label='Example multisim') + msim.run() + msim.summarize() # Prints moderate length output + ''' + labelstr = f' "{self.label}"' if self.label else '' + simlenstr = f'{len(self.sims)}' if self.sims else '0' + string = f'MultiSim{labelstr} summary:\n' + string += f' Number of sims: {simlenstr}\n' string += f' Reduced/combined: {self.which}\n' string += f' Base: {self.base_sim.brief(output=True)}\n' - string += ' Sims:\n' - for s,sim in enumerate(self.sims): - string += f' {s}: {sim.brief(output=True)}\n' + if self.sims: + string += ' Sims:\n' + for s,sim in enumerate(self.sims): + string += f' {s}: {sim.brief(output=True)}\n' if not output: print(string) else: return string - def brief(self): - ''' Print the sims, briefly ''' - for s,sim in enumerate(self.sims): - print(f'{s}: {sim.brief(output=True)}') - return + def _brief(self): + ''' + Return a brief description of a multisim -- used internally and by repr(); + see multisim.brief() for the user version. + ''' + try: + labelstr = f'"{self.label}"; ' if self.label else '' + string = f'MultiSim({labelstr}n_sims: {len(self.sims)}; base: {self.base_sim.brief(output=True)})' + except Exception as E: + string = sc.objectid(self) + string += f'Warning, multisim appears to be malformed:\n{str(E)}' + return string + + + def brief(self, output=False): + ''' + Print a compact representation of the multisim. See also multisim.disp() + (detailed output) and multisim.summarize() (medium length output). + + Args: + output (bool): if true, return a string instead of printing output + + **Example**:: + msim = cv.MultiSim(cv.Sim(verbose=0), label='Example multisim') + msim.run() + msim.brief() # Prints one-line output + ''' + string = self._brief() + if not output: + print(string) + else: + return string class Scenarios(cvb.ParsObj): @@ -731,23 +821,29 @@ class Scenarios(cvb.ParsObj): scenarios (dict) : a dictionary defining the scenarios; see examples folder for examples; see below for baseline basepars (dict) : a dictionary of sim parameters to be used for the basis of the scenarios (not required if sim is provided) scenfile (str) : a filename for saving (defaults to the creation date) + label (str) : the name of the scenarios + + **Example**:: + + scens = cv.Scenarios() Returns: scens: a Scenarios object ''' - def __init__(self, sim=None, metapars=None, scenarios=None, basepars=None, scenfile=None): + def __init__(self, sim=None, metapars=None, scenarios=None, basepars=None, scenfile=None, label=None): # For this object, metapars are the foundation default_pars = make_metapars() # Start with default pars super().__init__(default_pars) # Initialize and set the parameters as attributes + cvb.set_metadata(self) # Set version, date, and git info # Handle filename - self.created = sc.now() if scenfile is None: datestr = sc.getdate(obj=self.created, dateformat='%Y-%b-%d_%H.%M.%S') scenfile = f'covasim_scenarios_{datestr}.scens' self.scenfile = scenfile + self.label = label # Handle scenarios -- by default, create the simplest possible baseline scenario if scenarios is None: @@ -870,18 +966,7 @@ def print_heading(string): #%% Print statistics if verbose: - sc.heading('Results for last day in each scenario:') - x = defaultdict(dict) - scenkeys = list(self.scenarios.keys()) - for scenkey in scenkeys: - for reskey in reskeys: - val = self.results[reskey][scenkey].best[-1] - if reskey not in ['r_eff', 'doubling_time']: - val = int(val) - x[scenkey][reskey] = val - df = pd.DataFrame.from_dict(x).astype(object) - print(df) - print() + self.compare() # Save details about the run self._kept_people = keep_people @@ -889,6 +974,47 @@ def print_heading(string): return + def compare(self, t=None, output=False): + ''' + Print out a comparison of each scenario. + + Args: + t (int/str) : the day (or date) to do the comparison; default, the end + output (bool) : if true, return the dataframe instead of printing output + + **Example**:: + + scenarios = {'base': {'name':'Base','pars': {}}, 'beta': {'name':'Beta', 'pars': {'beta': 0.020}}} + scens = cv.Scenarios(scenarios=scenarios, label='Example scenarios') + scens.run() + scens.compare(t=30) # Prints comparison for day 30 + ''' + + # Handle time + if t is None: + t = -1 + daystr = 'the last day' + else: + daystr = f'day {t}' + day = self.base_sim.day(t) # Unlike MultiSims, scenarios must have the same start day + + # Compute dataframe + x = defaultdict(dict) + for scenkey in self.scenarios.keys(): + for reskey in self.result_keys(): + val = self.results[reskey][scenkey].best[day] + if reskey not in ['r_eff', 'doubling_time']: + val = int(val) + x[scenkey][reskey] = val + df = pd.DataFrame.from_dict(x).astype(object) + + if not output: + print(f'Results for {daystr} in each scenario:') + print(df) + else: + return df + + def plot(self, *args, **kwargs): ''' Plot the results of a scenario. @@ -1061,6 +1187,94 @@ def load(scenfile, *args, **kwargs): return scens + def disp(self, output=False): + ''' + Display a verbose description of the scenarios. See also scenarios.summarize() + (medium length output) and scenarios.brief() (short output). + + Args: + output (bool): if true, return a string instead of printing output + + **Example**:: + + scens = cv.Scenarios(cv.Sim(), label='Example scenarios') + scens.run(verbose=0) # Run silently + scens.disp() # Displays detailed output + ''' + string = self._disp() + if not output: + print(string) + else: + return string + + + def summarize(self, output=False): + ''' + Print a moderate length summary of the scenarios. See also scenarios.disp() + (detailed output) and scenarios.brief() (short output). + + Args: + output (bool): if true, return a string instead of printing output + + **Example**:: + + scens = cv.Scenarios(cv.Sim(), label='Example scenarios') + scens.run(verbose=0) # Run silently + scens.summarize() # Prints moderate length output + ''' + labelstr = f' "{self.label}"' if self.label else '' + string = f'Scenarios{labelstr} summary:\n' + string += f' Number of scenarios: {len(self.sims)}\n' + string += f' Base: {self.base_sim.brief(output=True)}\n' + if self.sims: + string += ' Scenarios:\n' + for k,key,simlist in self.sims.enumitems(): + keystr = f' {k}: "{key}"\n' + string += keystr + for s,sim in enumerate(simlist): + simstr = f'{sim.brief(output=True)}' + string += ' ' + f'{s}: {simstr}\n' + if not output: + print(string) + else: + return string + + + def _brief(self): + ''' + Return a brief description of the scenarios -- used internally and by repr(); + see scenarios.brief() for the user version. + ''' + try: + labelstr = f'"{self.label}"; ' if self.label else '' + string = f'Scenarios({labelstr}n_scenarios: {len(self.sims)}; base: {self.base_sim.brief(output=True)})' + except Exception as E: + string = sc.objectid(self) + string += f'Warning, scenarios appear to be malformed:\n{str(E)}' + return string + + + def brief(self, output=False): + ''' + Print a compact representation of the scenarios. See also scenarios.disp() + (detailed output) and scenarios.summarize() (medium length output). + + Args: + output (bool): if true, return a string instead of printing output + + **Example**:: + + scens = cv.Scenarios(label='Example scenarios') + scens.run() + scens.brief() # Prints one-line output + ''' + string = self._brief() + if not output: + print(string) + else: + return string + + def single_run(sim, ind=0, reseed=True, noise=0.0, noisepar=None, keep_people=False, run_args=None, sim_args=None, verbose=None, do_run=True, **kwargs): ''' Convenience function to perform a single simulation run. Mostly used for diff --git a/covasim/sim.py b/covasim/sim.py index 66413cc60..3f965ac6d 100644 --- a/covasim/sim.py +++ b/covasim/sim.py @@ -71,7 +71,7 @@ def __init__(self, pars=None, datafile=None, datacols=None, label=None, simfile= self._orig_pars = None # Store original parameters to optionally restore at the end of the simulation # Now update everything - self.set_metadata(simfile, label) # Set the simulation date and filename + self.set_metadata(simfile) # Set the simulation date and filename self.update_pars(pars, **kwargs) # Update the parameters, if provided self.load_data(datafile, datacols) # Load the data, if provided if self.load_pop: @@ -666,6 +666,13 @@ def finalize(self, verbose=None, restore_pars=True): if key not in preserved: self.pars[key] = self._orig_pars.pop(key) # Restore everything except for the analyzers and interventions + # Optionally print summary output + if verbose: # Verbose is any non-zero value + if verbose>0: # Verbose is any positive number + self.summarize() # Print medium-length summary of the sim + else: + self.brief() # Print brief summary of the sim + return @@ -675,7 +682,7 @@ def compute_results(self, verbose=None): self.compute_yield() self.compute_doubling() self.compute_r_eff() - self.summarize(verbose=verbose, update=True) + self.compute_summary() return @@ -827,7 +834,7 @@ def compute_r_eff(self, method='daily', smoothing=2, window=7): # Method not recognized else: - errormsg = f'Method must be "daily", "infected", or "outcome", not "{method}"' + errormsg = f'Method must be "daily", "infectious", or "outcome", not "{method}"' raise ValueError(errormsg) # Set the values and return @@ -871,75 +878,108 @@ def compute_gen_time(self): return self.results['gen_time'] - def summarize(self, full=False, t=None, verbose=None, output=False, update=True): + def compute_summary(self, full=None, t=None, update=True, output=False): ''' - Print a summary of the simulation, drawing from the last time point in the simulation. + Compute the summary dict and string for the sim. Used internally; see + sim.summarize() for the user version. Args: full (bool): whether or not to print all results (by default, only cumulative) t (int/str): day or date to compute summary for (by default, the last point) - verbose (bool): whether to print to screen (default: same as sim) + update (bool): whether to update the stored sim.summary output (bool): whether to return the summary - update (bool): whether to update the summary stored in the sim (sim.summary) ''' - if self.results_ready: + if t is None: + t = self.day(self.t) - if t is None: - t = self.day(self.t) + # Compute the summary + summary = sc.objdict() + for key in self.result_keys(): + summary[key] = self.results[key][t] - if verbose is None: - verbose = self['verbose'] + # Update the stored state + if update: + self.summary = summary - summary = sc.objdict() - for key in self.result_keys(): - summary[key] = self.results[key][t] + # Optionally return + if output: + return summary + else: + return - summary_str = 'Simulation summary:\n' - for key in self.result_keys(): - if full or key.startswith('cum_'): - summary_str += f' {summary[key]:5.0f} {self.results[key].name.lower()}\n' - if update: - self.summary = summary + def summarize(self, full=False, t=None, output=False): + ''' + Print a medium-length summary of the simulation, drawing from the last time + point in the simulation by default. Called by default at the end of a sim run. + See also sim.disp() (detailed output) and sim.brief() (short output). - if verbose: - if verbose>0: - print(summary_str) - else: - self.brief() + Args: + full (bool): whether or not to print all results (by default, only cumulative) + t (int/str): day or date to compute summary for (by default, the last point) + output (bool): whether to return the summary instead of printing it - if output: - return summary + **Examples**:: + + sim = cv.Sim(label='Example sim', verbose=0) # Set to run silently + sim.run() # Run the sim + sim.summarize() # Print medium-length summary of the sim + sim.summarize(t=24, full=True) # Print a "slice" of all sim results on day 24 + ''' + # Compute the summary + summary = self.compute_summary(full=full, t=t, update=False, output=True) + # Construct the output string + labelstr = f' "{self.label}"' if self.label else '' + string = f'Simulation{labelstr} summary:\n' + for key in self.result_keys(): + if full or key.startswith('cum_'): + string += f' {summary[key]:5.0f} {self.results[key].name.lower()}\n' + + # Print or return string + if not output: + print(string) else: - return self.brief(output=output) # If the simulation hasn't been run, default to the brief summary + return string - def brief(self, output=False): - ''' Return a one-line description of a sim ''' + def disp(self, output=False): + ''' + Display a verbose description of a sim. See also sim.summarize() (medium + length output) and sim.brief() (short output). - if self.results_ready: - infections = self.summary['cum_infections'] - deaths = self.summary['cum_deaths'] - results = f'{infections:n}⚙, {deaths:n}☠' - else: - results = 'not run' + Args: + output (bool): if true, return a string instead of printing output - if self.label: - label = f'"{self.label}"' - else: - label = '' + **Example**:: - start = sc.date(self['start_day'], as_date=False) - if self['end_day']: - end = sc.date(self['end_day'], as_date=False) + sim = cv.Sim(label='Example sim', verbose=0) # Set to run silently + sim.run() # Run the sim + sim.disp() # Displays detailed output + ''' + string = self._disp() + if not output: + print(string) else: - end = sc.date(self['n_days'], start_date=start) + return string - pop_size = self['pop_size'] - pop_type = self['pop_type'] - string = f'Sim({label}; {start} to {end}; pop: {pop_size:n} {pop_type}; epi: {results})' + def brief(self, output=False): + ''' + Print a one-line description of a sim. See also sim.disp() (detailed output) + and sim.summarize() (medium length output). The symbol "⚙" is used to show + infections, and "☠" is used to show deaths. + + Args: + output (bool): if true, return a string instead of printing output + + **Example**:: + + sim = cv.Sim(label='Example sim', verbose=0) # Set to run silently + sim.run() # Run the sim + sim.brief() # Prints one-line output + ''' + string = self._brief() if not output: print(string) else: diff --git a/docs/Makefile b/docs/Makefile index 58a4ea91e..5959a2161 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -50,6 +50,7 @@ clean: # The -f is to ignore missing files, not to force remove rm -rf $(BUILDDIR) rm -f covasim*.rst rm -f modules.rst + cd tutorials; ./clean_outputs .PHONY: generate-api diff --git a/docs/README.md b/docs/README.md index c02855e06..5f27ad9ac 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,7 +1,12 @@ # Covasim docs -This folder includes code for building the docs. Users are unlikely to need to -do this themselves. +## Tutorials + +Please see the `tutorials` subfolder. + +## Everything else + +This folder includes source code for building the docs. Users are unlikely to need to do this themselves. Instead, view the Covasim docs at http://docs.covasim.org. To build the docs, follow these steps: @@ -10,10 +15,6 @@ To build the docs, follow these steps: pip install -r requirements.txt ``` -2. Make the documents; there are many build options, but after ``build_docs``, most convenient is:: - - ``` - make html - ``` +2. Make the documents; there are many build options. In most cases, running `./build_docs` (to rerun the tutorials; takes 2 min) or `./build_docs never` (does not rebuild the tutorials; takes 15 s) is best. Alternatively, one can call `make html` directly. 3. The built documents will be in `./_build/html`. \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index f6e95673a..c8b8bc42f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -15,6 +15,7 @@ import subprocess import sys import sphinx_rtd_theme +import covasim as cv on_rtd = os.environ.get('READTHEDOCS') == 'True' @@ -82,7 +83,7 @@ # General information about the project. project = 'Covasim' -copyright = '2020, Bill & Melinda Gates Foundation. All rights reserved.' +copyright = f'2020, Bill & Melinda Gates Foundation. All rights reserved.\nThese docs were built for Covasim version {cv.__version__}.\n' author = 'Institute for Disease Modeling' # The version info for the project you're documenting, acts as replacement for @@ -90,7 +91,6 @@ # built documents. # # The short X.Y version. -import covasim as cv version = cv.__version__ # The full version, including alpha/beta/rc tags. release = cv.__version__ @@ -102,15 +102,6 @@ # Usually you set "language" from the command line for these cases. language = None -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# -# today = '' -# -# Else, today_fmt is used as the format for a strftime call. -# -# today_fmt = '%B %d, %Y' - # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path @@ -118,8 +109,6 @@ # suppress warnings for multiple possible Python references in the namespace # suppress_warnings = ['ref.python'] - - pygments_style = 'sphinx' # If true, `todo` and `todoList` produce output, else they produce nothing. @@ -127,7 +116,6 @@ # RST epilog is added to the end of every topic. Useful for replace # directives to use across the docset. - rst_epilog = "\n.. include:: /variables.txt" # -- Options for HTML output ---------------------------------------------- @@ -167,20 +155,15 @@ # bottom, using the given strftime format. # The empty string is equivalent to '%b %d, %Y'. # -html_last_updated_fmt = 'Y%-%b-%d' +html_last_updated_fmt = '%Y-%b-%d' # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. html_show_sphinx = False -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# -# html_show_copyright = True - # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -# html_use_opensearch = 'docs.idmod.org/projects/covasim/en/latest' # Output file base name for HTML help builder. diff --git a/docs/index.rst b/docs/index.rst index 9f03ae8eb..e2d4b834c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -13,7 +13,7 @@ Full contents :maxdepth: 4 overview - tutorials/README + tutorials whatsnew parameters data diff --git a/docs/requirements.txt b/docs/requirements.txt index 77934b658..d528c3f20 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -7,5 +7,4 @@ ipykernel nbsphinx pandoc pypandoc -optuna -numba==0.48 \ No newline at end of file +optuna \ No newline at end of file diff --git a/docs/tutorials.rst b/docs/tutorials.rst new file mode 100644 index 000000000..28d768629 --- /dev/null +++ b/docs/tutorials.rst @@ -0,0 +1,14 @@ +.. include:: tutorials/README.rst + +.. toctree:: + :maxdepth: 1 + + tutorials/t1 + tutorials/t2 + tutorials/t3 + tutorials/t4 + tutorials/t5 + tutorials/t6 + tutorials/t7 + tutorials/t8 + tutorials/t9 diff --git a/docs/tutorials/README.rst b/docs/tutorials/README.rst index 91f478efc..bb5fb9ad8 100644 --- a/docs/tutorials/README.rst +++ b/docs/tutorials/README.rst @@ -1,17 +1,5 @@ +========= Tutorials -=================================== +========= -These tutorials walk through how to use Covasim. If you want to explore them interactively, start a Jupyter environment in this folder (``docs/tutorials``). You can use either ``jupyter lab`` or ``jupyter notebook`` to run these tutorials. - -.. toctree:: - :maxdepth: 1 - - t1 - t2 - t3 - t4 - t5 - t6 - t7 - t8 - t9 +These tutorials walk through how to use Covasim. If you want to explore them interactively, start a Jupyter environment in this folder (``docs/tutorials``). You can use either ``jupyter lab`` or ``jupyter notebook`` to run these tutorials. \ No newline at end of file diff --git a/docs/tutorials/clean_outputs b/docs/tutorials/clean_outputs index 59f87f961..7ada973f8 100755 --- a/docs/tutorials/clean_outputs +++ b/docs/tutorials/clean_outputs @@ -1,3 +1,7 @@ #!/bin/bash -# Remove auto-generated files -rm -v ./my-*.* +# Remove auto-generated files; use -f in case they don't exist +echo 'Deleting:' +echo `ls -1 ./my-*.*` +echo '...in 3 seconds' +sleep 3 +rm -vf ./my-*.* \ No newline at end of file diff --git a/docs/tutorials/t1.ipynb b/docs/tutorials/t1.ipynb index 57ca62a05..369fa7640 100644 --- a/docs/tutorials/t1.ipynb +++ b/docs/tutorials/t1.ipynb @@ -20,7 +20,7 @@ "\n", "## Hello world\n", "\n", - "To create and run a sim with default options is just:" + "To create, run, and plot a sim with default options is just:" ] }, { @@ -32,14 +32,15 @@ "import covasim as cv\n", "\n", "sim = cv.Sim()\n", - "sim.run()" + "sim.run()\n", + "fig = sim.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Defining parameters\n", + "## Defining parameters and running simulations\n", "\n", "Parameters are defined as a dictionary. The most common parameters to modify are the population size, the initial number of people infected, and the start and end dates of the simulation. We can define those as:" ] @@ -62,8 +63,6 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Running a simulation\n", - "\n", "Running a simulation is pretty easy. In fact, running a sim with the parameters we defined above is just:" ] }, @@ -119,7 +118,7 @@ "source": [ "## Plotting results\n", "\n", - "Plotting the results of a simulation is rather easy too:" + "As you saw above, plotting the results of a simulation is rather easy too:" ] }, { @@ -131,40 +130,6 @@ "fig = sim.plot()" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Populations and contact network layers\n", - "\n", - "Agents in the simulation interact with each other via one or more *contact layers*. You can think of each agent as a node in a mathematical graph, and each connection as an edge. By default, Covasim creates a single random contact network where each agent is connected to 20 other agents, completely at random. However, this is not a very realistic representation of households, workplaces, schools, etc.\n", - "\n", - "For greater realism, Covasim also comes with a \"hybrid\" population option, which provides a more realism while still being fast to generate. (It's called \"hybrid\" because it's a combination of the random network and the [SynthPops](http://synthpops.org) network, described in Tutorial 9, which is much more realistic but requires a lot of data and is computationally intensive.) The hybrid option provides four *contact layers*: households (`'h'`), schools (`'s'`), workplaces (`'w'`), and community interactions (`'c'`). Each layer is defined by (a) which agents are connected to which other agents, and (b) the weight of each connection (i.e., transmission probability). Specifically:\n", - "* Households are small clusters, usually 2-5 people (depending on country), consisting of a wide variety of ages; this setting has high transmission probability\n", - "* Schools are split into classrooms, usually about 20 students each, of students aged 6–22; this setting has medium transmission probability\n", - "* Workplaces are clusters of about 5-20 people, aged (approximately) 22-65; this setting has medium transmission probability\n", - "* Community contacts (representing parks, restaurants, transport, places of worship, etc.) are estimated as 20 random contacts per day; this setting has low transmission probability\n", - "\n", - "Note that for most countries, you can load default data (age distribution and household size, both from the UN) by using the `location` keyword when creating a sim. For example, to create a realistic (i.e. hybrid) population 10,000 people for Bangladesh and plot the results, you would do:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "pars = dict(\n", - " pop_size = 10_000, # Alternate way of writing 10000\n", - " pop_type = 'hybrid',\n", - " location = 'Bangladesh', # Case insensitive\n", - ")\n", - "\n", - "sim = cv.Sim(pars)\n", - "sim.initialize() # Create people\n", - "fig = sim.people.plot() # Show statistics of the people" - ] - }, { "cell_type": "markdown", "metadata": {}, diff --git a/docs/tutorials/t2.ipynb b/docs/tutorials/t2.ipynb index adaf1dabd..77c7e50af 100644 --- a/docs/tutorials/t2.ipynb +++ b/docs/tutorials/t2.ipynb @@ -4,9 +4,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# T2 - Plotting and saving\n", + "# T2 - Plotting, printing, and saving\n", "\n", - "This tutorial provides a brief overview of options for plotting and saving results." + "This tutorial provides a brief overview of options for plotting results, printing objects, and saving results." ] }, { @@ -36,9 +36,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Plotting options\n", + "## Printing objects\n", "\n", - "While a sim can be plotted using default settings simply by `sim.plot()`, this is just a small fraction of what's available. First, note that results can be plotted directly using e.g. Matplotlib. You can see what quantities are available for plotting with `sim.results.keys()` (remember, it's just a dict). A simple example of plotting using Matplolib is:" + "There are three levels of detail available for most objects (sims, multisims, scenarios, and people). The shortest is `brief()`:" ] }, { @@ -47,17 +47,14 @@ "metadata": {}, "outputs": [], "source": [ - "import pylab as pl # Shortcut for import matplotlib.pyplot as plt\n", - "pl.plot(sim.results['date'], sim.results['new_infections'])" + "sim.brief()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "However, as you can see, this isn't ideal since the default formatting is...not great. (Also, note that each result is a `Result` object, not a simple Numpy array; like a pandas dataframe, you can get the array of values directly via e.g. `sim.results['new_infections'].values`.)\n", - "\n", - "An alternative, if you only want to plot a single result, such as new infections, is to use the `plot_result()` method:" + "You can get more detail with `summarize()`:" ] }, { @@ -66,14 +63,14 @@ "metadata": {}, "outputs": [], "source": [ - "sim.plot_result('new_infections')" + "sim.summarize()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "You can also select one or more quantities to plot with the `to_plot` argument, e.g." + "Finally, to show the full object, including all methods and attributes, use `disp()` (which is also the default if you just type `print(sim)`:" ] }, { @@ -82,14 +79,16 @@ "metadata": {}, "outputs": [], "source": [ - "sim.plot(to_plot=['new_infections', 'cum_infections'])" + "sim.disp()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Another useful option is to plot an overview of everything in a simulation. We can do this with the `to_plot='overview'` argument. It's quite a lot of information so we might also want to make a larger figure for it, which we can do by passing additional arguments via the `fig_args` argument (which is passed to `pl.figure()`)." + "## Plotting options\n", + "\n", + "While a sim can be plotted using default settings simply by `sim.plot()`, this is just a small fraction of what's available. First, note that results can be plotted directly using e.g. Matplotlib. You can see what quantities are available for plotting with `sim.results.keys()` (remember, it's just a dict). A simple example of plotting using Matplolib is:" ] }, { @@ -98,16 +97,17 @@ "metadata": {}, "outputs": [], "source": [ - "sim.plot(to_plot='overview', fig_args=dict(figsize=(30,15)))" + "import pylab as pl # Shortcut for import matplotlib.pyplot as plt\n", + "pl.plot(sim.results['date'], sim.results['new_infections'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Saving options\n", + "However, as you can see, this isn't ideal since the default formatting is...not great. (Also, note that each result is a `Result` object, not a simple Numpy array; like a pandas dataframe, you can get the array of values directly via e.g. `sim.results['new_infections'].values`.)\n", "\n", - "Saving is pretty simple. The simplest way to save is simply" + "An alternative, if you only want to plot a single result, such as new infections, is to use the `plot_result()` method:" ] }, { @@ -116,14 +116,14 @@ "metadata": {}, "outputs": [], "source": [ - "sim.save('my-awesome-sim.sim')" + "sim.plot_result('new_infections')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Technically, this saves as a gzipped pickle file (via `sc.saveobj()` using the Sciris library). By default this does not save the people in the sim since they are very large (and since, if the random seed is saved, they can usually be regenerated). If you want to save the people as well, you can use the `keep_people` argument. For example, here's what it would look like to create a sim, run it halfway, save it, load it, change the overall transmissibility (beta), and finish running it:" + "You can also select one or more quantities to plot with the `to_plot` argument, e.g." ] }, { @@ -132,21 +132,14 @@ "metadata": {}, "outputs": [], "source": [ - "sim_orig = cv.Sim(start_day='2020-04-01', end_day='2020-06-01', label='Load & save example')\n", - "sim_orig.run(until='2020-05-01')\n", - "sim_orig.save('my-half-finished-sim.sim') # Note: Covasim always saves the people if the sim isn't finished running yet\n", - "\n", - "sim = cv.load('my-half-finished-sim.sim')\n", - "sim['beta'] *= 0.3\n", - "sim.run()\n", - "sim.plot(to_plot=['new_infections', 'n_infectious', 'cum_infections'])" + "sim.plot(to_plot=['new_infections', 'cum_infections'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Aside from saving the entire simulation, there are other export options available. You can export the results and parameters to a JSON file (using `sim.to_json()`), but probably the most useful is to export the results to an Excel workbook, where they can easily be stored and processed with e.g. Pandas:" + "Another useful option is to plot an overview of everything in a simulation. We can do this with the `to_plot='overview'` argument. It's quite a lot of information so we might also want to make a larger figure for it, which we can do by passing additional arguments via the `fig_args` argument (which is passed to `pl.figure()`)." ] }, { @@ -155,18 +148,16 @@ "metadata": {}, "outputs": [], "source": [ - "import pandas as pd\n", - "\n", - "sim.to_excel('my-sim.xlsx')\n", - "df = pd.read_excel('my-sim.xlsx')\n", - "print(df)" + "sim.plot(to_plot='overview', fig_args=dict(figsize=(30,15)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Finally, there are a few options that are useful for viewing the output of a simulation. The most verbose, and possibly the least useful, is just printing the sim itself:" + "## Saving options\n", + "\n", + "Saving is pretty simple. The simplest way to save is simply" ] }, { @@ -175,14 +166,14 @@ "metadata": {}, "outputs": [], "source": [ - "print(sim)" + "sim.save('my-awesome-sim.sim')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "If a sim has been run, you can view the summary output:" + "Technically, this saves as a gzipped pickle file (via `sc.saveobj()` using the Sciris library). By default this does not save the people in the sim since they are very large (and since, if the random seed is saved, they can usually be regenerated). If you want to save the people as well, you can use the `keep_people` argument. For example, here's what it would look like to create a sim, run it halfway, save it, load it, change the overall transmissibility (beta), and finish running it:" ] }, { @@ -191,14 +182,21 @@ "metadata": {}, "outputs": [], "source": [ - "sim.summarize(verbose=True) # NB, we turned verbosity off above so have to turn it back on" + "sim_orig = cv.Sim(start_day='2020-04-01', end_day='2020-06-01', label='Load & save example')\n", + "sim_orig.run(until='2020-05-01')\n", + "sim_orig.save('my-half-finished-sim.sim') # Note: Covasim always saves the people if the sim isn't finished running yet\n", + "\n", + "sim = cv.load('my-half-finished-sim.sim')\n", + "sim['beta'] *= 0.3\n", + "sim.run()\n", + "sim.plot(to_plot=['new_infections', 'n_infectious', 'cum_infections'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Finally, if you want a really really brief overview of the sim, you can get that too:" + "Aside from saving the entire simulation, there are other export options available. You can export the results and parameters to a JSON file (using `sim.to_json()`), but probably the most useful is to export the results to an Excel workbook, where they can easily be stored and processed with e.g. Pandas:" ] }, { @@ -207,7 +205,11 @@ "metadata": {}, "outputs": [], "source": [ - "sim.brief()" + "import pandas as pd\n", + "\n", + "sim.to_excel('my-sim.xlsx')\n", + "df = pd.read_excel('my-sim.xlsx')\n", + "print(df)" ] } ], diff --git a/docs/tutorials/t4.ipynb b/docs/tutorials/t4.ipynb index aa7465b52..28374a8e9 100644 --- a/docs/tutorials/t4.ipynb +++ b/docs/tutorials/t4.ipynb @@ -4,13 +4,84 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# T4 - Working with data\n", + "# T4 - People and data\n", "\n", - "Modeling without data is like riding a bicycle while blindfolded –rarely dull, but often you don't get to where you want to go. This tutorial shows how to use data with Covasim.\n", + "Modeling without data is like riding a bicycle while blindfolded – rarely dull, but often you don't get to where you want to go. This tutorial shows how to use data with Covasim. But first, an introduction to people, populations, and contact layers." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## People and contact network layers\n", + "\n", + "Agents in Covasim are contained in an object called `People`, which contains all of the agents' properties, as well as methods for changing them from one state to another (e.g., from susceptible to infected).\n", + "\n", + "Agents interact with each other via one or more *contact layers*. You can think of each agent as a node in a mathematical graph, and each connection as an edge. By default, Covasim creates a single random contact network where each agent is connected to 20 other agents, completely at random. However, this is not a very realistic representation of households, workplaces, schools, etc.\n", + "\n", + "For greater realism, Covasim also comes with a \"hybrid\" population option, which provides a more realism while still being fast to generate. (It's called \"hybrid\" because it's a combination of the random network and the [SynthPops](http://synthpops.org) network, described in Tutorial 9, which is much more realistic but requires a lot of data and is computationally intensive.) The hybrid option provides four *contact layers*: households `'h'`, schools `'s'`, workplaces `'w'`, and community interactions `'c'`. Each layer is defined by (a) which agents are connected to which other agents, and (b) the weight of each connection (i.e., transmission probability). Specifically:\n", + "* Households are small clusters, usually 2-5 people (depending on country), consisting of a wide variety of ages; this setting has high transmission probability\n", + "* Schools are split into classrooms, usually about 20 students each, of students aged 6–22; this setting has medium transmission probability\n", + "* Workplaces are clusters of about 5-20 people, aged (approximately) 22-65; this setting has medium transmission probability\n", + "* Community contacts (representing parks, restaurants, transport, places of worship, etc.) are estimated as 20 random contacts per day; this setting has low transmission probability\n", + "\n", + "Note that for most countries, you can load default data (age distribution and household size, both from the UN) by using the `location` keyword when creating a sim. For example, to create a realistic (i.e. hybrid) population 10,000 people for Bangladesh and plot the results, you would do:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import covasim as cv\n", + "cv.options.set(dpi=100, show=False, close=True, verbose=0) # Standard options for Jupyter notebook\n", + "\n", + "pars = dict(\n", + " pop_size = 10_000, # Alternate way of writing 10000\n", + " pop_type = 'hybrid',\n", + " location = 'Bangladesh', # Case insensitive\n", + ")\n", + "\n", + "sim = cv.Sim(pars)\n", + "sim.initialize() # Create people\n", + "fig = sim.people.plot() # Show statistics of the people" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Demographic data\n", + "\n", + "Covasim includes pre-downloaded data on country (and US state) age distributions and household size distributions. As we saw in Tutorial 1, you can load these data simply by using the `location` parameter. You can show a list of all available locations with `cv.data.show_locations()`. The data themselves are simply a set of dictionaries, and thiese can be modified directly; for example, to add a custom age distribution for Johannesburg would look like this:\n", + "\n", + "```python\n", + "# Note data format and key names!\n", + "joburg_pop = {\n", + " '0-9': 286620,\n", + " '10-19': 277020,\n", + " '20-29': 212889,\n", + " '30-39': 161329,\n", + " '40-49': 104399,\n", + " '50-59': 51716,\n", + " '60-69': 36524,\n", + " '70-79': 22581,\n", + " '80+': 7086}\n", "\n", - "## Data scrapers\n", + "cv.data.country_age_data.data['Johannesburg'] = joburg_pop\n", + "```\n", "\n", - "Covasim includes a script to automatically download time series data on diagnoses, deaths, and other information from several major sources of COVID-19 data. These include the [Corona Data Scraper](https://coronadatascraper.com), the [European Centre for Disease Prevention and\n", + "You can then use these data via `sim = cv.Sim(location='Johannesburg')`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Epidemiological data scrapers\n", + "\n", + "Covasim includes a script to automatically download time series data on diagnoses, deaths, and other epidemiological information from several major sources of COVID-19 data. These include the [Corona Data Scraper](https://coronadatascraper.com), the [European Centre for Disease Prevention and\n", "Control](https://www.ecdc.europa.eu/en/geographical-distribution-2019-ncov-cases), and the [COVID Tracking Project](https://covidtracking.com). These scrapers provide data for a large number of locations (over 4000 at the time of writing), including the US down to the county level and many other countries down to the district level. The data they download is already in the correct format for Covasim.\n", "\n", "## Data input and formats\n", @@ -42,7 +113,7 @@ "source": [ "
\n", " \n", - "**Note:** Sometimes date information fails to be read properly, especially when loading from Excel files. See Tutorial 8 for help on fixing this.\n", + "**Note:** Sometimes date information fails to be read properly, especially when loading from Excel files via pandas. If you encounter this problem, see Tutorial 8 for help on fixing this.\n", " \n", "
" ] @@ -60,9 +131,6 @@ "metadata": {}, "outputs": [], "source": [ - "import covasim as cv\n", - "cv.options.set(dpi=100, show=False, close=True, verbose=0) # Standard options for Jupyter notebook\n", - "\n", "pars = dict(\n", " start_day = '2020-02-01',\n", " end_day = '2020-04-11',\n", diff --git a/docs/tutorials/t5.ipynb b/docs/tutorials/t5.ipynb index e4c1bc7a7..29fd9380d 100644 --- a/docs/tutorials/t5.ipynb +++ b/docs/tutorials/t5.ipynb @@ -45,6 +45,7 @@ "metadata": {}, "source": [ "A few things to note here:\n", + "\n", "* By default, interventions are shown with vertical dashed lines. You can turn this off by passing `do_plot=False` to the intervention.\n", "* Look at the new infections plot (middle) for the clearest illustration of the impact the intervention has.\n", "* Note that like other \"parameters\", you can either pass interventions to the sim directly or as part of the pars dictionary; the exmaples below illustrate these options.\n", @@ -57,6 +58,7 @@ "```\n", "\n", "The \"clip edges\" intervention works similarly to the \"change beta\" intervention, with two important distinctions:\n", + "\n", "1. Whereas beta changes affect the per-contact transmission probability, clip edges change the number of contacts. For example, in the `close_schools` example above, each school-aged child has an uncanged number of contacts (about 20), but 10 times lower probability of infection per contact (about 0.1% per contact per day). If clip edges were used instead, then each child would have unchanged probability of infection per contact (about 1% per contact per day), but 10 times fewer contacts (about 2).\n", "2. While beta changes can be any value (greater or less than 1), as the name implies, clip edges can only *clip* edges, not create new ones. Edges that are clipped are saved and can later be restored, but you can never have a change of greater than 1.0 with clip edges." ] @@ -79,6 +81,7 @@ "## Testing interventions\n", "\n", "There are two types of testing interventions in Covasim:\n", + "\n", "1. `test_num` performs the specified *number* of tests per day;\n", "2. `test_prob` performs testing with the specified *probability*.\n", "\n", @@ -395,7 +398,8 @@ "metadata": {}, "source": [ "While this example is fairly long, hopefully it's fairly straightforward:\n", - "- **`__init__()`** just does what init always does; it's needed to create the class instance. For interentions, it's usually used to store keyword arguments and perform some basic initialization (the first two lines).\n", + "\n", + "- **__init__()** just does what init always does; it's needed to create the class instance. For interentions, it's usually used to store keyword arguments and perform some basic initialization (the first two lines).\n", "- **initialize()** is similar to init, with the difference that it's invoked when the *sim* itself is initialized. It receives the sim as an input argument. This means you can use it to do a fairly powerful things. Here, since `sim.people` already exists, we can calculate up-front who the elderly are so we don't have to do it on every timestep.\n", "- **apply()** is the crux of the intervention. It's run on every timestep of the model, and also receives `sim` as an input. You almost always use `sim.t` to get the current timestep, here to turn the intervention on and off. But as this example shows, its real power is that it can make direct modifications to the sim itself (`sim.people.rel_sus[self.elderly] = self.rel_sus`). It can also perform calculations and store data in itself, as shown here with `self.exposed` (although in general, analyzers are better for this, since they happen at the end of the timestep, while interventions happen in the middle).\n", "- **plot()** is a custom method that shows a plot of the data gathered during the sim. Again, it's usually better to use analyzers for this, but for something simple like this it's fine to double-dip and use an intervention.\n",