Analisando dados XLSX de World Population Prospects (WPP) em Python

As Nações Unidas fornecem o conjunto de dados Word Population Prospects (WPP) sobre distribuição geográfica e etária da humanidade como arquivos XLSX baixáveis.

Ler estes arquivos em Python é bastante fácil. Primeiro temos que descobrir quantas linhas pular. Para o conjunto de dados WPP 2019 este valor é 16 já que a linha 17 contém todos os cabeçalhos das colunas. O número de linhas a pular pode ser diferente dependendo do conjunto de dados. Estamos usando WPP2019_POP_F07_1_POPULATION_BY_AGE_BOTH_SEXES.xlsx neste exemplo.

Podemos usar a função read_excel() do Pandas para importar o conjunto de dados em Python:

read_wpp_excel.py
import pandas as pd

df = pd.read_excel("WPP2019_INT_F03_1_POPULATION_BY_AGE_ANNUAL_BOTH_SEXES.xlsx", skiprows=16, na_values=["..."])

Isso levará alguns segundos até que o grande conjunto de dados tenha sido processado. Agora podemos verificar se skiprows=16 é o valor correto. Está correto se pandas reconheceu os nomes das colunas corretamente:

df_columns_output.txt
>>> 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')

Agora vamos filtrar por um país:

filter_russia.py
russia = df[df["Region, subregion, country or area *"] == 'Russian Federation']

Isso nos mostrará os dados de população para múltiplos anos em intervalos de 5 anos de 1950 a 2020. Agora vamos filtrar pelo ano mais recente:

most_recent_russia.py
russia.loc[russia["Reference date (as of 1 July)"].idxmax()]

Isso nos mostrará um único conjunto de dados:

most_recent_russia_output.txt
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

Como podemos plotar esses dados? Primeiro, precisamos selecionar todas as colunas que contêm dados de idade. Faremos isso inserindo manualmente o nome da primeira coluna (0-4) no código a seguir e assumindo que não há colunas após a última coluna de idade:

age_columns_index.py
>>> 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')

Agora vamos selecionar essas colunas do conjunto de dados russia:

prepare_russian_age_data.py
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]

Vamos dar uma olhada no conjunto de dados:

russian_age_data_output.txt
>>> 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

Isso parece utilizável, note entretanto que os valores estão em milhares, i.e. temos que multiplicar os valores por 1000 para obter as estimativas reais da população. Vamos plotar:

plot_russian_age_data.py
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)

O gráfico finalizado se parecerá com isto:

Composição etária da população russa em 2020 plotada como um gráfico de linhas

Aqui está nosso script finalizado:

russian_demographics_plot.py
#!/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")

Check out similar posts by category: Bioinformatics Data Science Pandas Python