3
\$\begingroup\$

How can I improve this code's readability and function, for finding crude death rate and age specific death rate? Given are the death rates from chronic pulmonary obstructive disease in 2019, the populations, and the World Health Organisation standard population rates.

import numpy as np

us_death_rates = np.array(
    [
        0.04,
        0.02,
        0.02,
        0.02,
        0.06,
        0.11,
        0.29,
        0.56,
        1.42,
        4.00,
        14.13,
        37.22,
        66.48,
        108.66,
        213.10,
        333.06,
        491.10,
        894.45,
    ]
)

uganda_death_rates = np.array(
    [
        0.40,
        0.17,
        0.07,
        0.23,
        0.38,
        0.40,
        0.75,
        1.11,
        2.04,
        5.51,
        13.26,
        33.25,
        69.62,
        120.78,
        229.88,
        341.06,
        529.31,
        710.40,
    ]
)

us_population_by_age_group = np.array(
    [
        19849000,
        20697000,
        22092000,
        21895000,
        21872000,
        23407000,
        22842000,
        22297000,
        20695000,
        21244000,
        21346000,
        22348000,
        20941000,
        17501000,
        13689000,
        9273000,
        6119000,
        6214000,
    ]
)

uganda_population_by_age_group = np.array(
    [
        7329000,
        6614000,
        5899000,
        5151000,
        4348000,
        3500000,
        2619000,
        1903000,
        1504000,
        1235000,
        953000,
        687000,
        500000,
        353000,
        197000,
        93000,
        44000,
        20000,
    ]
)

who_standard_weights = np.array(
    [
        8.86,
        8.69,
        8.6,
        8.47,
        8.22,
        7.93,
        7.61,
        7.15,
        6.59,
        6.04,
        5.37,
        4.55,
        3.72,
        2.96,
        2.21,
        1.52,
        0.91,
        0.63,
    ]
)


def calculate_total_deaths(population_by_age_group, death_rates):
    return np.sum((population_by_age_group / 100000) * death_rates)

def crude_death_rate(population_by_age_group, total_deaths):
     return (total_deaths/np.sum(population_by_age_group))*(10**5)

def age_standardised_death_rate(population_by_age_group, standard_weights, death_rates):
    standard_deaths = np.sum(
            (population_by_age_group / 100000)
            * standard_weights
            * death_rates
    )
    total_standard_population = np.sum(population_by_age_group * standard_weights)
    return (standard_deaths / total_standard_population) * (10**5)

us_total_deaths = calculate_total_deaths(us_population_by_age_group, us_death_rates)
uganda_total_deaths = calculate_total_deaths(uganda_population_by_age_group, uganda_death_rates)

us_crude_death_rate = crude_death_rate(us_population_by_age_group, us_total_deaths)
uganda_crude_death_rate = crude_death_rate(uganda_population_by_age_group, uganda_total_deaths)

us_age_standardised_death_rate = age_standardised_death_rate(us_population_by_age_group, who_standard_weights, us_death_rates)
uganda_age_standardised_death_rate = age_standardised_death_rate(uganda_population_by_age_group, who_standard_weights, uganda_death_rates)

print(f"US crude death rate: {us_crude_death_rate:.1f}")
print(f"Uganda crude death rate: {uganda_crude_death_rate:.1f}")
print(f"US age standardised death rate: {us_age_standardised_death_rate:.1f}")
print(f"Uganda age standardised death rate: {uganda_age_standardised_death_rate:.1f}")
\$\endgroup\$
3
  • \$\begingroup\$ Since you incorporated feedback from the answers in your follow-up question, please reward one with an Accept \$\endgroup\$
    – toolic
    Mar 20 at 19:19
  • \$\begingroup\$ @toolic I thank you so much for your feedback. Sorry, but I don't know which answer to accept as I found every idea helpful, and was delighted to learn, and build from your ideas. \$\endgroup\$ Mar 23 at 9:44
  • 1
    \$\begingroup\$ Glad to help. I'll make the decision easy for you -- accept the other answer. I just want someone to get the extra rep :) \$\endgroup\$
    – toolic
    Mar 23 at 10:16

2 Answers 2

4
\$\begingroup\$

The big issue I see in the code is its readability given that I, not being familiar with the WHO statistics, do not understand what is being calculated. This also makes it difficult to suggest improvements to the code.

What Are Your Inputs and What Are You Calculating?

You have variable names such as us_death_rates defined as an array of numbers, but what do the numbers represent? Do these represent a percentage of the total population? Or perhaps they are an absolute number of deaths for every N people in the population. For example, the first element might represent .04 deaths per N people. If that is the case, what would N be? 100? 1000? The confusion persists when you print the results as numbers with captions that do not clarify what the numbers represent. And each element is describing a specific age group, but what is an age group? If it's a range of ages I would like to know that the first element represents, for example, people between the ages of 0 and 5 years old.

You should (1) Provide a comment for each array documenting exactly what is being described and (2) Use more descriptive names that help us remember what is being described. For example, if the first array represented death rate percentages for each age group, then a more descriptive name would be us_death_rate_percentages_by_age_group.

Each Function Should Describe What Is Being Calculated

At the very least each function should have a docstring describing what is being calculated and what the arguments used for the calculation are. If you choose to add type hinting, that would be a plus.

The Output Needs Clarification

People who do not read the code but view the output (I, for one) would not necessarily understand what is being outputted. For example, you print in part:

US crude death rate: 57.2

I have no idea what the 57.2 represents? 57.2 percent of the population dies every year (I doubt it's that)? 57.2 people per 1000 die each month (maybe)? Help, I am drowning in numbers that hold no meaning for me.

Good News!

Only a few comments, docstrings, renaming of variables and better captions on your output are all that should be required to greatly improve both readability and usability of the code..

\$\endgroup\$
2
\$\begingroup\$

Overview

You've done an excellent job:

  • You did a good job partitioning code into functions
  • You leveraged code written by others with the import
  • Used meaningful names for functions and variables

Here are some adjustments for you to consider, mainly for coding style.

Layout

I recommend moving the functions to the top, after the import statement. Having them in the middle of the code interrupts the natural flow of the code (from a human readability standpoint).

Lint check

pylint identified a few style issues. There are some long lines that can be shortened.

It also identified inconsistent indentation on one line.

You can use the black program to automatically modify the code for you.

Documentation

You should documentation to the top of your file to state the purpose of the code. The PEP 8 style guide recommends that you add docstrings for your methods.

Data

There is a lot of data in your code. You could consider storing the data in external text files and reading it into your arrays. That would make the code more flexible should the data change.

Readability

For large numbers like 100000, it is nice to use the underscore separator: 100_000.

Also, you have 100000 in some places and 10**5 in others. I'd go with 100_000 everywhere for consistency.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.