在 Python 中解析 World Population Prospects (WPP) XLSX 数据

联合国提供 World Population Prospects (WPP) 数据集,包含人类地理和年龄分布,可作为 XLSX 文件下载。

在 Python 中读取这些文件相当容易。首先我们必须找出要跳过多少行。对于 2019 WPP 数据集,此值为 16,因为第 17 行包含所有列标题。要跳过的行数可能因数据集而异。在此示例中我们使用 WPP2019_POP_F07_1_POPULATION_BY_AGE_BOTH_SEXES.xlsx

我们可以使用 Pandas read_excel() 函数在 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=["..."])

这将需要几秒钟来处理大型数据集。现在我们可以检查 skiprows=16 是否是正确的值。如果 pandas 正确识别了列名,则它是正确的:

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')

现在让我们过滤国家

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

这将显示从 19502020 以 5 年为间隔的多年人口数据。现在让我们过滤最近的年份:

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

这将显示单个数据集:

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

我们如何绘制该数据?首先,我们需要选择包含年龄数据的所有列。我们将通过手动将第一个此类列的名称(0-4)插入以下代码,并假设最后一个年龄列之后没有列:

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')

现在让我们从 russia 数据集中选择这些列:

russian_age_data = most_recent_russia[age_columns]

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]

让我们看看数据集:

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

这看起来可用,但注意值以千为单位,即我们必须将值乘以 1000 以获取实际人口估计值。让我们绘制它:

plot_russian_age_data.py
from matplotlib import pyplot as plt
plt.style.use("ggplot")

plt.title("俄罗斯人口年龄构成 (2020)")
plt.ylabel("年龄组人数 [百万]")
plt.xlabel("年龄组")
plt.gcf().set_size_inches(15,5)
# 数据以千为单位 => 除以 1000 获取百万
plt.plot(russian_age_data.index, russian_age_data.as_matrix() / 1000., lw=3)

完成的图将看起来像这样:

2020 年俄罗斯人口年龄构成折线图

这是我们完成的脚本:

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)
# 仅过滤俄罗斯
russia = df[df["Region, subregion, country or area *"] == 'Russian Federation']

# 仅过滤最近估计(1 行)
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]

# 绘制!
from matplotlib import pyplot as plt
plt.style.use("ggplot")

plt.title("俄罗斯人口年龄构成 (2020)")
plt.ylabel("年龄组人数 [百万]")
plt.xlabel("年龄组")
plt.gcf().set_size_inches(15,5)
# 数据以千为单位 => 除以 1000 获取百万
plt.plot(russian_age_data.index, russian_age_data.as_matrix() / 1000., lw=3)

# 导出为 SVG
plt.savefig("russian-demographics.svg")

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