Организация Объединённых Наций предоставляет набор данных Word Population Prospects (WPP) о географическом и возрастном распределении человечества в виде скачиваемых XLSX-файлов.
Читать эти файлы в Python довольно просто. Сначала нам нужно выяснить, сколько строк нужно пропустить. Для набора данных WPP 2019 года это значение равно 16, поскольку строка 17 содержит все заголовки столбцов. Количество строк для пропуска может отличаться в зависимости от набора данных. В этом примере мы используем WPP2019_POP_F07_1_POPULATION_BY_AGE_BOTH_SEXES.xlsx.
Мы можем использовать функцию Pandas read_excel() для импорта набора данных в Python:
import pandas as pd
df = pd.read_excel("WPP2019_INT_F03_1_POPULATION_BY_AGE_ANNUAL_BOTH_SEXES.xlsx", skiprows=16, na_values=["..."])Это займёт несколько секунд, пока большой набор данных будет обработан. Теперь мы можем проверить, является ли skiprows=16 правильным значением. Оно корректно, если pandas правильно распознал имена столбцов:
>>> df.columns
Index(['Index', 'Variant', 'Region, subregion, country or area *', 'Notes',
'Country code', 'Type', 'Parent code', 'Reference date (as of 1 July)',
'0-4', '5-9', '10-14', '15-19', '20-24', '25-29', '30-34', '35-39',
'40-44', '45-49', '50-54', '55-59', '60-64', '65-69', '70-74', '75-79',
'80-84', '85-89', '90-94', '95-99', '100+'],
dtype='object')Теперь давайте отфильтруем по стране:
russia = df[df["Region, subregion, country or area *"] == 'Russian Federation']Это покажет нам данные о населении за несколько лет с 5-летними интервалами от 1950 до 2020. Теперь давайте отфильтруем по самому последнему году:
russia.loc[russia["Reference date (as of 1 July)"].idxmax()]Это покажет нам один набор данных:
Index 3255
Variant Estimates
Region, subregion, country or area * Russian Federation
Notes NaN
Country code 643
Type Country/Area
Parent code 923
Reference date (as of 1 July) 2020
0-4 9271.69
5-9 9350.92
10-14 8174.26
15-19 7081.77
20-24 6614.7
25-29 8993.09
30-34 12543.8
35-39 11924.7
40-44 10604.6
45-49 9770.68
50-54 8479.65
55-59 10418
60-64 10073.6
65-69 8427.75
70-74 5390.38
75-79 3159.34
80-84 3485.78
85-89 1389.64
90-94 668.338
95-99 102.243
100+ 9.407
Name: 3254, dtype: objectКак мы можем построить график этих данных? Сначала нам нужно выбрать все столбцы, содержащие данные о возрасте. Мы сделаем это, вручную вставив имя первого такого столбца (0-4) в следующий код и предполагая, что после последнего столбца возраста нет других столбцов:
>>> df.columns[df.columns.get_loc("0-4"):]
Index(['0-4', '5-9', '10-14', '15-19', '20-24', '25-29', '30-34', '35-39',
'40-44', '45-49', '50-54', '55-59', '60-64', '65-69', '70-74', '75-79',
'80-84', '85-89', '90-94', '95-99', '100+'],
dtype='object')Теперь давайте выберем эти столбцы из набора данных russia:
most_recent_russia = russia.loc[russia["Reference date (as of 1 July)"].idxmax()]
age_columns = df.columns[df.columns.get_loc("0-4"):]
russian_age_data = most_recent_russia[age_columns]Давайте посмотрим на набор данных:
>>> russian_age_data
0-4 9271.69
5-9 9350.92
10-14 8174.26
15-19 7081.77
20-24 6614.7
25-29 8993.09
30-34 12543.8
35-39 11924.7
40-44 10604.6
45-49 9770.68
50-54 8479.65
55-59 10418
60-64 10073.6
65-69 8427.75
70-74 5390.38
75-79 3159.34
80-84 3485.78
85-89 1389.64
90-94 668.338
95-99 102.243
100+ 9.407Это выглядит пригодным для использования, однако обратите внимание, что значения указаны в тысячах, т.е. нам нужно умножить значения на 1000, чтобы получить фактические оценки населения. Давайте построим график:
from matplotlib import pyplot as plt
plt.style.use("ggplot")
plt.title("Age composition of the Russian population (2020)")
plt.ylabel("People in age group [Millions]")
plt.xlabel("Age group")
plt.gcf().set_size_inches(15,5)
# Data is given in thousands => divide by 1000 to obtain millions
plt.plot(russian_age_data.index, russian_age_data.as_matrix() / 1000., lw=3)Готовый график будет выглядеть так:
Вот наш готовый скрипт:
#!/usr/bin/env python3
import pandas as pd
df = pd.read_excel("WPP2019_POP_F07_1_POPULATION_BY_AGE_BOTH_SEXES.xlsx", skiprows=16)
# Filter only russia
russia = df[df["Region, subregion, country or area *"] == 'Russian Federation']
# Filter only most recent estimate (1 row)
most_recent_russia = russia.loc[russia["Reference date (as of 1 July)"].idxmax()]
# Retain only value columns
age_columns = df.columns[df.columns.get_loc("0-4"):]
russian_age_data = most_recent_russia[age_columns]
# Plot!
from matplotlib import pyplot as plt
plt.style.use("ggplot")
plt.title("Age composition of the Russian population (2020)")
plt.ylabel("People in age group [Millions]")
plt.xlabel("Age group")
plt.gcf().set_size_inches(15,5)
# Data is given in thousands => divide by 1000 to obtain millions
plt.plot(russian_age_data.index, russian_age_data.as_matrix() / 1000., lw=3)
# Export as SVG
plt.savefig("russian-demographics.svg")