Home > front end >  Why do I get a warning and negative numbers when I try to project the world population in Python?
Why do I get a warning and negative numbers when I try to project the world population in Python?

Time:04-19

I am trying to build a quadratic model to study the evolution of the world population. I would like to display the evolution of the world population until 2100 using the quadratic model.

I took my data from Worldometer. I downloaded the page and read it with Pandas.

Here is my code:

# Import of modules
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from types import SimpleNamespace

# Reading the file
Data = 'World Population by Year - Worldometer.html'
Data2 = pd.read_html(Data, header = 0, index_col = 0, decimal = 'M')

Data3 = Data2[0] # We extract a DataFrame from the file

Given the year jumps and the fact that the data may not have been reliable prior to 1951, I removed all data prior to 1951 to work only on data from 1951 to 2020.

# Delete the years before 1951
data = Data3.drop(Data.index[70:], axis = 0)

# Rename the names of the columns
data.index.names = ['Year'] # Rename the index
data.columns = ['Population', 'Annual change', 'Net change', 'Density (P/Km²)', 'Urban population', 'Urban population (%)'] # Renaming of other columns

population = data['Population']

total_growth = population[2020] - population[1951]

start = population.index[-1] # 1st year of data collected
current = population.index[0] # Last year of data collected
duration = current - start # Duration of the data collection period

start_population = population[start]
population_2020 = population[current]
difference_population = population_2020 - start_population

annual_growth = total_growth / duration

parameters = SimpleNamespace(start = start, end = current, start_population = start_population, annual_growth = annual_growth)

def model(parameters, growth_function):
    result = dict()
    result[parameters.start] = parameters.start_population
    
    for t in range(parameters.start, parameters.end):
        evolution = growth_function(t, result[t], parameters)
        result[t   1] = result[t]   evolution
        
    # We convert the dictionary into a DataFrame in order to plot it
    result_items = result.items() # To obtain an object of type set with the keys  and the values of the dictionary
    result_list = list(result_items) # We then convert the set object into a list
    results = pd.DataFrame(result_list) # Finally we create a DataFrame from a list
    
    results.columns = ['Year', 'World population'] # Name of the columns of the DataFrame
    
    return results

parameters.alpha = parameters.birth_rate - parameters.death_rate

def quadratic(t, population, parameters):
    """Returns the quadratic function"""
    return parameters.alpha * population   parameters.beta * population ** 2

Parameters = SimpleNamespace(start = start, start_population = start_population, alpha = 25 / 1000, beta = -1.8 / 1000, end = 2100)

projection = model(Parameters, quadratic)
projection

Here is the result I get by running this code:

Year World Population
0 1951 2.584034e 09
1 1952 -1.201902e 16
2 1953 -2.600222e 29
3 1954 -1.217008e 56
4 1955 -2.665994e 109
... ... ...
145 2096 -inf
146 2097 -inf
147 2098 -inf
148 2099 -inf
149 2100 -inf

As you can see, I get totally inconsistent results from the first year calculated (i.e. 1952) and I don't know where this dysfunction can come from. Moreover, I get a RuntimeWarning: overflow encountered in double_scalars warning when I try to display the results of the simulation even if this does not prevent the result from being displayed.

No matter how hard I look, I can't figure out what's wrong with my code and my initial values. Where do you think these two problems come from?

CodePudding user response:

I added some code to show you why you get the RunTimeError.

def quadratic(t, population, parameters):
    """Returns the quadratic function"""
    print(t)
    return parameters.alpha * population   (parameters.beta * population) ** 2

Parameters = SimpleNamespace(start = start, start_population = start_population, alpha = 25 / 1000, beta = -1.8 / 1000, end = 2100)

np.seterr(all='raise')
projection = model(Parameters, quadratic)
projection

The 'RunTimeError' is because the numbers are getting too big. The line np.seterr(all='raise') in front of your function call changes the warning to an error. In the quadratic function I added print(t) to see where the error occurs. You will see, if you run your code again, at year 1957 you will get an error because the number in (parameters.beta * population) ** 2 is too big to be handled by numpy.float64 Even if you start to calculate everything in millions, the error will appear at year 2019. You need to convert the population to billions. To do that just add the devision when defining population at the beginning.

population = data['Population'] --> population = data['Population']/1_000_000_000

Done all that projection will show you a table with actual numbers (in billions)

CodePudding user response:

Your beta parameter is negative (beta = -1.8 / 1000). According to your quadratic equation

parameters.alpha * population   parameters.beta * population ** 2

you multiply the variable population in the second term by a negative number . And since you also raise it to a power of 2, at some point the second term (death rate) outweighs the first term (birth rate) enough to make the result negative.

Also, in order to avoid the overflow problem, you should measure population in millions instead.

  • Related