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.