Get the "Applied Data Science Edge"!

The ViralML School

Fundamental Market Analysis with Python - Find Your Own Answers On What Is Going on in the Financial Markets

Web Work

Python Web Work - Prototyping Guide for Maker

Use HTML5 Templates, Serve Dynamic Content, Build Machine Learning Web Apps, Grow Audiences & Conquer the World!

Hot off the Press!

The Little Book of Fundamental Market Indicators

My New Book: "The Little Book of Fundamental Analysis: Hands-On Market Analysis with Python" is Out!

Free Udemy Class - Exploring Population Pyramids and Building Data Science Web Apps

Introduction

Join me for this free Udemy class where we will explore Population Pyramids using Python and we'll even build a web application where you'll be able to choose a country, a continent, even the whole world, and choose the a year, it can the current one, a past one, or even peer into the future and it will build these automatically.



If you liked it, please share it:

Code

ViralML-Population-Pyramids
In [1]:
import matplotlib.pyplot as plt
from IPython.display import Image
Image(filename='population pyramid thumb.png', width='80%')
Out[1]:

Let's talk about population pyramids! Almost as mysterious as the pyramids of Giza where you have to dig deep to find the hidden treasures... well not really, but you definitely should dig and I'll show you how to dig using python and where to get curated and accurate data from the United Nations that covers most countries around the world! You'll even be able to dial back in time or dial forward into the future! Exciting!

Sign up for my newsletter so you can get my free classes!

It breaks down a population, for whatever zone, a town, country, continent, world, into even age buckets and charts them into a bar plot. Traditionally males go on the left and females on the right, and I even stereotyped the coloring, and I don't like stereotypes but as I have less than an hour to prep these videos... there can only be so much imagination spent.

As you can see, it forms a sideways distribution by gender and together with a sort of pyramid. A healthy society should form a pyramid, a bit like a pyramid scheme, with more younger people joining the workforce and taking care of a lesser amount of older people - but that isn't always the case.

There are 3 overaching groups:

Expansive

A healthy zone where there are more people joining the workforce and able to take care of their elders - challenges are having affordable education and enough jobs.

Constrictive

There are too many old people and not enough young to take care of them, this is going to be a burden on the working-age folks to take care of the older ones, you'll need a lot of healthcare, geriatric and palliative type care that is very time consuming and expensive.

Stationary - a sort of equilibirum.

Let's dig into the code and we won't cover too much of the analysis but if you take this on, you can take this very far and understand things better understand birth rates, fertility, aging populations, the types of pressures a society will face, human migrations, etc. 

In [2]:
 
# Source: http://darkroom.baltimoresun.com/2016/10/building-human-towers-in-catalonia-spain/#1
Image(filename='Spain-Catalonia-Human-Towers-Castellers-10032016-18.jpg', width='80%')
Out[2]:
In [3]:
 
Image(filename='us_pop_pyr_1970.png', width='80%')
Out[3]:

Population Pyramid

https://en.wikipedia.org/wiki/Population_pyramid

"A population pyramid also called an "age-sex-pyramid", is a graphical illustration that shows the distribution of various age groups in a population (typically that of a country or region of the world), which forms the shape of a pyramid when the population is growing.[1] Males are conventionally shown on the left and females on the right, and they may be measured by the raw numbers or as a percentage of the total population. This tool can be used to visualize and age of a particular population.[2] It is also used in ecology to determine the overall age distribution of a population; an indication of the reproductive capabilities and likelihood of the continuation of a species."

Get the data - U.N. Department of Economic and Social Affairs - Population Dynamics

https://population.un.org/wpp/Download/Standard/CSV/

Medium variant, annual, from 1950 to 2100 (CSV, 113.05 MB)

In [4]:
# Current top bottom up, top up down
import numpy as np
import pandas as pd
pop_df = pd.read_csv('WPP2019_PopulationByAgeSex_Medium.csv')
print(pop_df.shape)
pop_df.head()
(1404753, 12)
Out[4]:
LocID Location VarID Variant Time MidPeriod AgeGrp AgeGrpStart AgeGrpSpan PopMale PopFemale PopTotal
0 4 Afghanistan 2 Medium 1950 1950.5 0-4 0 5 630.044 661.578 1291.622
1 4 Afghanistan 2 Medium 1950 1950.5 5-9 5 5 516.206 487.335 1003.541
2 4 Afghanistan 2 Medium 1950 1950.5 10-14 10 5 461.378 423.326 884.704
3 4 Afghanistan 2 Medium 1950 1950.5 15-19 15 5 414.369 369.363 783.732
4 4 Afghanistan 2 Medium 1950 1950.5 20-24 20 5 374.109 318.392 692.501

Plotting Population Pyramids

In [5]:
sorted(list(set(pop_df['Location'] ) ) )
Out[5]:
['Afghanistan',
 'Africa',
 'African Group',
 'African Union',
 'African Union: Central Africa',
 'African Union: Eastern Africa',
 'African Union: Northern Africa',
 'African Union: Southern Africa',
 'African Union: Western Africa',
 'African, Caribbean and Pacific (ACP) Group of States',
 'Albania',
 'Algeria',
 'Andean Community',
 'Angola',
 'Antigua and Barbuda',
 'Argentina',
 'Armenia',
 'Aruba',
 'Asia',
 'Asia-Pacific Economic Cooperation (APEC)',
 'Asia-Pacific Group',
 'Association of Southeast Asian Nations (ASEAN)',
 'Australia',
 'Australia/New Zealand',
 'Austria',
 'Azerbaijan',
 'BRIC',
 'BRICS',
 'Bahamas',
 'Bahrain',
 'Bangladesh',
 'Barbados',
 'Belarus',
 'Belgium',
 'Belize',
 'Belt-Road Initiative (BRI)',
 'Belt-Road Initiative: Africa',
 'Belt-Road Initiative: Asia',
 'Belt-Road Initiative: Europe',
 'Belt-Road Initiative: Latin America and the Caribbean',
 'Belt-Road Initiative: Pacific',
 'Benin',
 'Bhutan',
 'Black Sea Economic Cooperation (BSEC)',
 'Bolivarian Alliance for the Americas (ALBA)',
 'Bolivia (Plurinational State of)',
 'Bosnia and Herzegovina',
 'Botswana',
 'Brazil',
 'Brunei Darussalam',
 'Bulgaria',
 'Burkina Faso',
 'Burundi',
 'Cabo Verde',
 'Cambodia',
 'Cameroon',
 'Canada',
 'Caribbean',
 'Caribbean Community and Common Market (CARICOM)',
 'Central African Republic',
 'Central America',
 'Central Asia',
 'Central European Free Trade Agreement (CEFTA)',
 'Central and Southern Asia',
 'Chad',
 'Channel Islands',
 'Chile',
 'China',
 'China (and dependencies)',
 'China, Hong Kong SAR',
 'China, Macao SAR',
 'China, Taiwan Province of China',
 'Colombia',
 'Commonwealth of Independent States (CIS)',
 'Commonwealth of Nations',
 'Commonwealth: Africa',
 'Commonwealth: Asia',
 'Commonwealth: Caribbean and Americas',
 'Commonwealth: Europe',
 'Commonwealth: Pacific',
 'Comoros',
 'Congo',
 'Costa Rica',
 'Countries with Access to the Sea',
 'Countries with Access to the Sea: Africa',
 'Countries with Access to the Sea: Asia',
 'Countries with Access to the Sea: Europe',
 'Countries with Access to the Sea: Latin America and the Caribbean',
 'Countries with Access to the Sea: Northern America',
 'Countries with Access to the Sea: Oceania',
 'Croatia',
 'Cuba',
 'Curaçao',
 'Cyprus',
 'Czechia',
 "Côte d'Ivoire",
 "Dem. People's Republic of Korea",
 'Democratic Republic of the Congo',
 'Denmark',
 'Denmark (and dependencies)',
 'Djibouti',
 'Dominican Republic',
 'ECE: North America-2',
 'ECE: UNECE-52',
 'ECLAC: Latin America',
 'ECLAC: The Caribbean',
 'ESCAP region: East and North-East Asia',
 'ESCAP region: North and Central Asia',
 'ESCAP region: Pacific',
 'ESCAP region: South and South-West Asia',
 'ESCAP region: South-East Asia',
 'ESCAP: ADB Developing member countries (DMCs)',
 'ESCAP: ADB Group A (Concessional assistance\xa0only)',
 'ESCAP: ADB Group B\xa0(OCR blend)',
 'ESCAP: ADB Group C (Regular OCR only)',
 'ESCAP: ASEAN',
 'ESCAP: Central Asia',
 'ESCAP: ECO',
 'ESCAP: HDI groups',
 'ESCAP: Landlocked countries (LLDCs)',
 'ESCAP: Least Developed Countries (LDCs)',
 'ESCAP: Pacific island dev. econ.',
 'ESCAP: SAARC',
 'ESCAP: WB High income econ.',
 'ESCAP: WB Low income econ.',
 'ESCAP: WB Lower middle income econ.',
 'ESCAP: WB Upper middle income econ.',
 'ESCAP: WB income groups',
 'ESCAP: high HDI',
 'ESCAP: high income',
 'ESCAP: income groups',
 'ESCAP: low HDI',
 'ESCAP: low income',
 'ESCAP: lower middle HDI',
 'ESCAP: lower middle income',
 'ESCAP: other Asia-Pacific countries/areas',
 'ESCAP: upper middle HDI',
 'ESCAP: upper middle income',
 'ESCWA: Arab countries',
 'ESCWA: Arab least developed countries',
 'ESCWA: Gulf Cooperation Council countries',
 'ESCWA: Maghreb countries',
 'ESCWA: Mashreq countries',
 'ESCWA: member countries',
 'East African Community (EAC)',
 'Eastern Africa',
 'Eastern Asia',
 'Eastern Europe',
 'Eastern European Group',
 'Eastern and South-Eastern Asia',
 'Economic Community of Central African States (ECCAS)',
 'Economic Community of West African States (ECOWAS)',
 'Economic Cooperation Organization (ECO)',
 'Ecuador',
 'Egypt',
 'El Salvador',
 'Equatorial Guinea',
 'Eritrea',
 'Estonia',
 'Eswatini',
 'Ethiopia',
 'Eurasian Economic Community (Eurasec)',
 'Europe',
 'Europe (48)',
 'Europe and Northern America',
 'European Community (EC: 12)',
 'European Free Trade Agreement (EFTA)',
 'European Union (EU: 15)',
 'European Union (EU: 28)',
 'Fiji',
 'Finland',
 'France',
 'France (and dependencies)',
 'French Guiana',
 'French Polynesia',
 'Gabon',
 'Gambia',
 'Georgia',
 'Germany',
 'Ghana',
 'Greater Arab Free Trade Area (GAFTA)',
 'Greece',
 'Grenada',
 'Group of 77 (G77)',
 'Group of Eight (G8)',
 'Group of Seven (G7)',
 'Group of Twenty (G20) - member states',
 'Guadeloupe',
 'Guam',
 'Guatemala',
 'Guinea',
 'Guinea-Bissau',
 'Gulf Cooperation Council (GCC)',
 'Guyana',
 'Haiti',
 'High-income countries',
 'Honduras',
 'Hungary',
 'Iceland',
 'India',
 'Indonesia',
 'Iran (Islamic Republic of)',
 'Iraq',
 'Ireland',
 'Israel',
 'Italy',
 'Jamaica',
 'Japan',
 'Jordan',
 'Kazakhstan',
 'Kenya',
 'Kiribati',
 'Kuwait',
 'Kyrgyzstan',
 'LLDC: Africa',
 'LLDC: Asia',
 'LLDC: Europe',
 'LLDC: Latin America',
 'Land-locked Countries',
 'Land-locked Countries (Others)',
 'Land-locked Developing Countries (LLDC)',
 "Lao People's Democratic Republic",
 'Latin America and the Caribbean',
 'Latin American Integration Association (ALADI)',
 'Latin American and Caribbean Group (GRULAC)',
 'Latvia',
 'League of Arab States (LAS, informal name: Arab League)',
 'Least developed countries',
 'Least developed: Africa',
 'Least developed: Asia',
 'Least developed: Latin America and the Caribbean',
 'Least developed: Oceania',
 'Lebanon',
 'Lesotho',
 'Less developed regions',
 'Less developed regions, excluding China',
 'Less developed regions, excluding least developed countries',
 'Less developed: Africa',
 'Less developed: Asia',
 'Less developed: Latin America and the Caribbean',
 'Less developed: Oceania',
 'Liberia',
 'Libya',
 'Lithuania',
 'Low-income countries',
 'Lower-middle-income countries',
 'Luxembourg',
 'Madagascar',
 'Malawi',
 'Malaysia',
 'Maldives',
 'Mali',
 'Malta',
 'Martinique',
 'Mauritania',
 'Mauritius',
 'Mayotte',
 'Melanesia',
 'Mexico',
 'Micronesia',
 'Micronesia (Fed. States of)',
 'Middle Africa',
 'Middle-income countries',
 'Mongolia',
 'Montenegro',
 'More developed regions',
 'More developed: Asia',
 'More developed: Europe',
 'More developed: Northern America',
 'More developed: Oceania',
 'Morocco',
 'Mozambique',
 'Myanmar',
 'Namibia',
 'Nepal',
 'Netherlands',
 'Netherlands (and dependencies)',
 'New Caledonia',
 'New EU member states (joined since 2004)',
 'New Zealand',
 'New Zealand (and dependencies)',
 'Nicaragua',
 'Niger',
 'Nigeria',
 'No income group available',
 'Non-Self-Governing Territories',
 'North American Free Trade Agreement (NAFTA)',
 'North Atlantic Treaty Organization (NATO)',
 'North Macedonia',
 'Northern Africa',
 'Northern Africa and Western Asia',
 'Northern America',
 'Northern Europe',
 'Norway',
 'Oceania',
 'Oceania (excluding Australia and New Zealand)',
 'Oman',
 'Organisation for Economic Co-operation and Development (OECD)',
 'Organization for Security and Co-operation in Europe (OSCE)',
 'Organization of American States (OAS)',
 'Organization of Petroleum Exporting countries (OPEC)',
 'Organization of the Islamic Conference (OIC)',
 'Pakistan',
 'Panama',
 'Papua New Guinea',
 'Paraguay',
 'Peru',
 'Philippines',
 'Poland',
 'Polynesia',
 'Portugal',
 'Puerto Rico',
 'Qatar',
 'Republic of Korea',
 'Republic of Moldova',
 'Romania',
 'Russian Federation',
 'Rwanda',
 'Réunion',
 'SIDS Atlantic, and Indian Ocean, Mediterranean and South China Sea (AIMS)',
 'SIDS Caribbean',
 'SIDS Pacific',
 'Saint Lucia',
 'Saint Vincent and the Grenadines',
 'Samoa',
 'Sao Tome and Principe',
 'Saudi Arabia',
 'Senegal',
 'Serbia',
 'Seychelles',
 'Shanghai Cooperation Organization (SCO)',
 'Sierra Leone',
 'Singapore',
 'Slovakia',
 'Slovenia',
 'Small Island Developing States (SIDS)',
 'Solomon Islands',
 'Somalia',
 'South Africa',
 'South America',
 'South Asian Association for Regional Cooperation (SAARC)',
 'South Sudan',
 'South-Eastern Asia',
 'Southern Africa',
 'Southern African Development Community (SADC)',
 'Southern Asia',
 'Southern Common Market (MERCOSUR)',
 'Southern Europe',
 'Spain',
 'Sri Lanka',
 'State of Palestine',
 'Sub-Saharan Africa',
 'Sudan',
 'Suriname',
 'Sweden',
 'Switzerland',
 'Syrian Arab Republic',
 'Tajikistan',
 'Thailand',
 'Timor-Leste',
 'Togo',
 'Tonga',
 'Trinidad and Tobago',
 'Tunisia',
 'Turkey',
 'Turkmenistan',
 'UN-ECE: member countries',
 'UNFPA Regions',
 'UNFPA: Arab States (AS)',
 'UNFPA: Asia and the Pacific (AP)',
 'UNFPA: East and Southern Africa (ESA)',
 'UNFPA: Eastern Europe and Central Asia (EECA)',
 'UNFPA: Latin America and the Caribbean (LAC)',
 'UNFPA: West and Central Africa (WCA)',
 'UNICEF PROGRAMME REGIONS',
 'UNICEF Programme Regions: East Asia and Pacific (EAPRO)',
 'UNICEF Programme Regions: Eastern Caribbean',
 'UNICEF Programme Regions: Eastern and Southern Africa (ESARO)',
 'UNICEF Programme Regions: Europe and Central Asia (CEECIS)',
 'UNICEF Programme Regions: Latin America',
 'UNICEF Programme Regions: Latin America and Caribbean (LACRO)',
 'UNICEF Programme Regions: Middle East and North Africa (MENARO)',
 'UNICEF Programme Regions: South Asia (ROSA)',
 'UNICEF Programme Regions: West and Central Africa (WCARO)',
 'UNICEF REGIONS',
 'UNICEF Regions: East Asia and Pacific',
 'UNICEF Regions: Eastern Europe and Central Asia',
 'UNICEF Regions: Eastern and Southern Africa',
 'UNICEF Regions: Europe and Central Asia',
 'UNICEF Regions: Latin America and Caribbean',
 'UNICEF Regions: Middle East and North Africa',
 'UNICEF Regions: North America',
 'UNICEF Regions: South Asia',
 'UNICEF Regions: Sub-Saharan Africa',
 'UNICEF Regions: West and Central Africa',
 'UNICEF Regions: Western Europe',
 'UNITED NATIONS Regional Groups of Member States',
 'Uganda',
 'Ukraine',
 'United Arab Emirates',
 'United Kingdom',
 'United Kingdom (and dependencies)',
 'United Nations Economic Commission for Africa (UN-ECA)',
 'United Nations Economic Commission for Latin America and the Caribbean (UN-ECLAC)',
 'United Nations Economic and Social Commission for Asia and the Pacific (UN-ESCAP) Regions',
 'United Nations Member States',
 'United Republic of Tanzania',
 'United States Virgin Islands',
 'United States of America',
 'United States of America (and dependencies)',
 'Upper-middle-income countries',
 'Uruguay',
 'Uzbekistan',
 'Vanuatu',
 'Venezuela (Bolivarian Republic of)',
 'Viet Nam',
 'WB region: East Asia and Pacific (excluding high income)',
 'WB region: Europe and Central Asia (excluding high income)',
 'WB region: Latin America and Caribbean (excluding high income)',
 'WB region: Middle East and North Africa (excluding high income)',
 'WB region: South Asia (excluding high income)',
 'WB region: Sub-Saharan Africa (excluding high income)',
 'WHO Regions',
 'WHO: African region (AFRO)',
 'WHO: Americas (AMRO)',
 'WHO: Eastern Mediterranean Region (EMRO)',
 'WHO: European Region (EURO)',
 'WHO: South-East Asia region (SEARO)',
 'WHO: Western Pacific region (WPRO)',
 'West African Economic and Monetary Union (UEMOA)',
 'Western Africa',
 'Western Asia',
 'Western Europe',
 'Western European and Others Group (WEOG)',
 'Western Sahara',
 'World',
 'World Bank Regional Groups (developing only)',
 'Yemen',
 'Zambia',
 'Zimbabwe']
In [6]:
len(list(set(pop_df['Location'])))
Out[6]:
440
In [7]:
print(np.min(pop_df['Time']), np.max(pop_df['Time']))
1950 2100
In [8]:
pop_df_tmp = pop_df[(pop_df['Location']=='Japan') & (pop_df['Time']==2020)]
pop_df_tmp = pop_df_tmp.sort_values('AgeGrpStart',ascending=True)
pop_df_tmp.head()
Out[8]:
LocID Location VarID Variant Time MidPeriod AgeGrp AgeGrpStart AgeGrpSpan PopMale PopFemale PopTotal
661038 392 Japan 2 Medium 2020 2020.5 0-4 0 5 2453.834 2324.647 4778.481
661039 392 Japan 2 Medium 2020 2020.5 5-9 5 5 2773.482 2628.006 5401.488
661040 392 Japan 2 Medium 2020 2020.5 10-14 10 5 2856.888 2707.638 5564.526
661041 392 Japan 2 Medium 2020 2020.5 15-19 15 5 2926.787 2775.858 5702.645
661042 392 Japan 2 Medium 2020 2020.5 20-24 20 5 3075.580 2921.297 5996.877
In [9]:
country = 'United States of America'
year = 1970

pop_df_tmp = pop_df[(pop_df['Location']==country) & (pop_df['Time']==year)]
pop_df_tmp = pop_df_tmp.sort_values('AgeGrpStart',ascending=True)

y = range(0, len(pop_df_tmp))
x_male = pop_df_tmp['PopMale']
x_female = pop_df_tmp['PopFemale']

# max xlim
max_x_scale = max(max(x_female), max(x_male))

fig, axes = plt.subplots(ncols=2, sharey=True, figsize=(10, 8))

fig.patch.set_facecolor('xkcd:Beige')
plt.figtext(.5,.9,country + ": " +  str(year), fontsize=15, ha='center')

axes[0].barh(y, x_male, align='center', color='lightblue')
axes[0].set(title='Males')
axes[0].set(xlim=[0,max_x_scale])
axes[1].barh(y, x_female, align='center', color='pink')
axes[1].set(title='Females')
axes[1].set(xlim=[0,max_x_scale])
axes[1].grid()
axes[0].set(yticks=y, yticklabels=pop_df_tmp['AgeGrp'])
axes[0].invert_xaxis()
axes[0].grid()

plt.show()
In [11]:
def plot_poulation_pyramid(country, year):
    pop_df_tmp = pop_df[(pop_df['Location']==country) & (pop_df['Time']==year)]
    pop_df_tmp = pop_df_tmp.sort_values('AgeGrpStart',ascending=True)

    y = range(0, len(pop_df_tmp))
    x_male = pop_df_tmp['PopMale']
    x_female = pop_df_tmp['PopFemale']
    
    # max xlim
    max_x_scale = max(max(x_female), max(x_male))

    fig, axes = plt.subplots(ncols=2, sharey=True, figsize=(10, 8))

    fig.patch.set_facecolor('xkcd:Beige')
    plt.figtext(.5,.9,country + ": " +  str(year), fontsize=15, ha='center')


    axes[0].barh(y, x_male, align='center', color='lightblue')
    axes[0].set(title='Males')
    axes[0].set(xlim=[0,max_x_scale])
    axes[1].barh(y, x_female, align='center', color='pink')
    axes[1].set(title='Females')
    axes[1].set(xlim=[0,max_x_scale])
    axes[1].grid()
    axes[0].set(yticks=y, yticklabels=pop_df_tmp['AgeGrp'])
    axes[0].invert_xaxis()
    axes[0].grid()
    plt.show()

Qatar - Highest Male Ratio

In [12]:
country = 'Qatar'
year = 2020
plot_poulation_pyramid(country, year)

Sierra Leone

In [13]:
country = 'Estonia'
year = 2020
plot_poulation_pyramid(country, year)

Libya

In [14]:
country = 'Libya'
year = 2020
plot_poulation_pyramid(country, year)

Europe

In [15]:
country = 'Europe (48)'
year = 2020
plot_poulation_pyramid(country, year)

Japan

In [16]:
country = 'Japan'
year = 2095
plot_poulation_pyramid(country, year)

Spain

In [17]:
country = 'Spain'
year = 2020
plot_poulation_pyramid(country, year)

Make a Matplotlib Animation

In [18]:
country='World'
counter = 0
for yr in list(range(1950,2100,1)):
    year = yr
    pop_df_tmp = pop_df[(pop_df['Location']==country) & (pop_df['Time']==year)]
    pop_df_tmp = pop_df_tmp.sort_values('AgeGrpStart',ascending=True)

    y = range(0, len(pop_df_tmp))
    x_male = pop_df_tmp['PopMale']
    x_female = pop_df_tmp['PopFemale']
    
    # max xlim
    max_x_scale = max(max(x_female), max(x_male))

    fig, axes = plt.subplots(ncols=2, sharey=True, figsize=(10, 8))

    fig.patch.set_facecolor('xkcd:Beige')
    plt.figtext(.5,.9,country + ": " +  str(year), fontsize=30, ha='center')


    axes[0].barh(y, x_male, align='center', color='lightblue')
    axes[0].set(title='Males')
    axes[0].set(xlim=[0,max_x_scale])
    axes[1].barh(y, x_female, align='center', color='pink')
    axes[1].set(title='Females')
    axes[1].set(xlim=[0,max_x_scale])
    axes[1].grid()
    axes[0].set(yticks=y, yticklabels=pop_df_tmp['AgeGrp'])
    axes[0].invert_xaxis()
    axes[0].grid()
    
    
    plt.savefig('movie/anim_' + str(counter) + '.png')
    counter += 1

     
     
    
In [ ]:
# make a video out of it...
# if you need help installing FFMPEG:
# https://github.com/adaptlearning/adapt_authoring/wiki/Installing-FFmpeg

ffmpeg -framerate 10 -i "anim_%d.png" -pix_fmt yuv420p out.mp4

Building our Population Pyramid Building Web Application

We are going to base our web portal on a great and fully resposive HTML template from the w3Schools:

https://www.w3schools.com/w3css/w3css_templates.asp

Make sure you go through the Flask tutorial if you haven't already done so and get yourself a PythonAnywhere account as shown in the previous class.

Create a new folder called 'flask_app_financial_portal' and upload the following files in their appropriate folders:

udemy-population-pyramids
    ├── flask_app.py
    ├── WPP2019_PopulationByAgeSex.csv
    └── templates 
            └── build-a-pyramid.html
In [7]:
# Create a smaller version to fit through the 100 MB limit on PythonAnywhere
pop_df = pd.read_csv('WPP2019_PopulationByAgeSex_Medium.csv')
pop_df = pop_df[['Location','Time', 'AgeGrp', 'AgeGrpStart', 'PopMale', 'PopFemale']]
pop_df.to_csv('WPP2019_PopulationByAgeSex.csv')
pop_df.head()
Out[7]:
Location Time AgeGrp AgeGrpStart PopMale PopFemale
0 Afghanistan 1950 0-4 0 630.044 661.578
1 Afghanistan 1950 5-9 5 516.206 487.335
2 Afghanistan 1950 10-14 10 461.378 423.326
3 Afghanistan 1950 15-19 15 414.369 369.363
4 Afghanistan 1950 20-24 20 374.109 318.392

flask_app.py

In [ ]:
#!/usr/bin/env python
from flask import Flask, render_template, flash, request, jsonify, Markup
import matplotlib
import matplotlib.pyplot as plt
import io, os, base64
import numpy as np
import pandas as pd

# global variables
app = Flask(__name__)
pop_df = None
location_list = None

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

@app.before_first_request
def startup():
	global pop_df, location_list

	# load and prepare the data
	pop_df = pd.read_csv(BASE_DIR + '/WPP2019_PopulationByAgeSex.csv')
	location_list = sorted(list(set(pop_df['Location'])))

def get_poulation_pyramid(country, year):
	pop_df_tmp = pop_df[(pop_df['Location']==country) & (pop_df['Time']==year)].copy()
	pop_df_tmp = pop_df_tmp.sort_values('AgeGrpStart',ascending=True)
	return(pop_df_tmp)

@app.route("/", methods=['POST', 'GET'])
def build_pyramid():
	plot_to_show = ''
	selected_country = ''
	country_list = ''
	selected_year = ''

	if request.method == 'POST':
		selected_country = request.form['selected_country']
		selected_year = int(request.form['selected_year'])

		pop_df_tmp = get_poulation_pyramid(selected_country, selected_year)

		y = range(0, len(pop_df_tmp))
		x_male = pop_df_tmp['PopMale']
		x_female = pop_df_tmp['PopFemale']

		# max xlim
		max_x_scale = max(max(x_female), max(x_male))

		fig, axes = plt.subplots(ncols=2, sharey=True, figsize=(12, 10))

		fig.patch.set_facecolor('xkcd:Beige')
		plt.figtext(.5,.9,selected_country + ": " +  str(selected_year), fontsize=15, ha='center')

		axes[0].barh(y, x_male, align='center', color='lightblue')
		axes[0].set(title='Males')
		axes[0].set(xlim=[0,max_x_scale])
		axes[1].barh(y, x_female, align='center', color='pink')
		axes[1].set(title='Females')
		axes[1].set(xlim=[0,max_x_scale])
		axes[1].grid()
		axes[0].set(yticks=y, yticklabels=pop_df_tmp['AgeGrp'])
		axes[0].invert_xaxis()
		axes[0].grid()

		img = io.BytesIO()
		plt.savefig(img, format='png')
		img.seek(0)
		plot_url = base64.b64encode(img.getvalue()).decode()
		plot_to_show = Markup('<img src="data:image/png;base64,{}" style="width:100%;vertical-align:top">'.format(plot_url))

	return render_template('build-a-pyramid.html',
						plot_to_show = plot_to_show,
						selected_country = selected_country,
						location_list = location_list,
						selected_year = selected_year)



if __name__=='__main__':
    app.run(debug=True)

build-a-pyramid.html

<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>Population Pyramids</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
  <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">

</head>

<body bgcolor="black">
  <div class="w3-center w3-padding">
    <H1><font color='lightblue'>ViralML</font> <font color='white'>Population</font> <font color='pink'>Pyramids</font></H1>

    <FORM id='submit_content' method="POST" action="{{ url_for('build_pyramid') }}">

    <SELECT class="selectpicker" name="selected_country">
        <option value="" selected></option>
       
    </SELECT>


    <SELECT class="selectpicker" name="selected_year" >
        <option value="" selected></option>
        
            <option value="1950">1950</option>
        
            <option value="1960">1960</option>
        
            <option value="1970">1970</option>
        
            <option value="1980">1980</option>
        
            <option value="1990">1990</option>
        
            <option value="2000">2000</option>
        
            <option value="2010">2010</option>
        
            <option value="2020">2020</option>
        
            <option value="2030">2030</option>
        
            <option value="2040">2040</option>
        
            <option value="2050">2050</option>
        
            <option value="2060">2060</option>
        
            <option value="2070">2070</option>
        
            <option value="2080">2080</option>
        
            <option value="2090">2090</option>
        
    </SELECT>
    <button type="submit" form="submit_content" value="Submit">Build</button>
  </FORM>
</div>



  

</body>

</html>

Show Notes

(pardon typos and formatting -
these are the notes I use to make the videos)

Join me for this free Udemy class where we will explore Population Pyramids using Python and we'll even build a web application where you'll be able to choose a country, a continent, even the whole world, and choose the a year, it can the current one, a past one, or even peer into the future and it will build these automatically.