主成分分析(PCA)用_世界の統計データの作成
前書き
オリンピックで柔道を見て日本代表の姿に感動していたAIエンジニアです。子供の頃はあまり感じていませんでしたが、最近"道の精神"の良さを感じる機会が増えてきたような気がします。色んな道があると思いますが一人の人間として大事にしていきたいものですね。
前回の記事では主成分分析(Principal component analysis: PCA)の哲学(考え方)と理論の部分をまとめました。
今回は実装部分をまとめる予定でしたが、データの作成部分で思ったより長くなってしまったので一度区切りたいと思います。
データの作成
さっそくデータの作成を実施していきます。
使用するデータ
せっかくなので他の方があまりやってないデータで試したいと思い色々探しました。
個人的な興味関心も踏まえ、総務省統計局が提供してくださっている世界の統計のデータを利用したいと思います。
出典:「世界の統計2024」(総務省統計局) (URL) (2024年7月25日に利用)
様々な統計データがまとまっていますが今回は、
・1-3 森林の面積
・2-4 人口・面積
・2-13 出生率の推移
・2-15 死亡率の推移
・2-16 男女別平均寿命・健康寿命(2019年)
・3-2 国内総生産(名目GDP、米ドル表示)
を使用することにします。これらのデータを個別に整理した後、1つのテーブルデータとしてまとめていきます。
ディレクトリ構成
元のファイルはエクセル形式になっています。1つの表(テーブル)を1ファイルとして使用した方が扱いやすいので、使用するデータをcsv形式に保存し直してから分析を行います。データごとにテーブルの数も異なるため、複数ある場合は末尾に番号を追加することにします。
↓それぞれのデータとcsvで保存したファイル名、ファイル数をまとめるとこんな感じになります。
data name | file base name | num of file |
---|---|---|
1-3 森林の面積 | 20240725_world_natural_area | 2 |
2-4 人口・面積 | 20240725_world_population | 6 |
2-13 出生率の推移 | 20240725_world_birth_rate | 1 |
2-15 死亡率の推移 | 20240725_world_death_rate | 1 |
2-16 男女別平均寿命・健康寿命(2019年) | 20240725_world_life_expectancy | 1 |
3-2 国内総生産(名目GDP、米ドル表示) | 20240725_world_gdp | 2 |
↓ディレクトリ構成はこんな感じです。
workspace
└input_data
├ 20240725_world_natural_area1.csv
├ 20240725_world_natural_area2.csv
├ 20240725_world_population1.csv
├ 20240725_world_population2.csv
├ 20240725_world_population3.csv
├ 20240725_world_population4.csv
├ 20240725_world_population5.csv
├ 20240725_world_population6.csv
├ 20240725_world_birth_rate.csv
├ 20240725_world_death_rate.csv
├ 20240725_world_life_expectancy.csv
├ 20240725_world_gdp1.csv
└ 20240725_world_gdp2.csv
それぞれのデータごとの整形
森林の面積
まずは森林の面積のデータです。
各国の陸地の面積や森林の面積、森林面積の変化などがまとまっています。
(以下、元ページの説明の引用)
1-3 森林の面積
〔出典〕
FAO, Global Forest Resources Assessment 2020
2020年10月ダウンロード〔解説〕
森林:高さ5メートル以上の樹木で覆われた0.5ヘクタール以上の土地で、林地に対する樹冠面積が10パーセント以上のもの(現在幼木であっても、将来樹冠面積10パーセント、高さ5メートルに達すると予想されるものを含む。)。人工林を含む。国立公園、自然保護地域、各種保護地域、防風林、ゴム園などを含み、果樹林などのように、農林業としての利用目的が明確なものを除く。陸地面積:内水面(主要な河川及び湖沼)を除いた総土地面積。
さっそく1つ目のcsvファイルを読み込んでみます。
import os
import pandas as pd
dir_path = "workspace_dir/input_data"
file_name = "20240725_world_natural_area1.csv"
data_path = os.path.join(dir_path, file_name)
natural_area_df1 = pd.read_csv(data_path)
natural_area_df1
結果を見てみると、
1-3 森林の面積(1) | Unnamed: 1 | Unnamed: 2 | Unnamed: 3 | Unnamed: 4 | Unnamed: 5 | Unnamed: 6 | Unnamed: 7 | |
---|---|---|---|---|---|---|---|---|
0 | nan | nan | nan | nan | nan | nan | nan | nan |
1 | 国(地域) | nan | 森林面積(2020年) | nan | nan | 森林面積の純変化 | nan | nan |
2 | nan | 陸地面積 | nan | nan | nan | (2010年~2020年) | nan | nan |
3 | nan | nan | 総面積 | 陸地に占 | 人工林 | 年平均 | 年平均 | nan |
4 | nan | nan | nan | める割合 | nan | nan | 増減率 | nan |
5 | nan | (1,000ha) | (1,000ha) | (%) | (1,000ha) | (1,000ha) | (%) | nan |
6 | nan | nan | nan | nan | nan | nan | nan | nan |
7 | アジア | nan | nan | nan | nan | nan | nan | nan |
8 | 日本 | 36,456 | 24,935 | 68.4 | 10,184 | -3.1 | -0.0 | nan |
9 | イラン | 162,876 | 10,752 | 6.6 | 1,001 | 6.0 | 0.1 | nan |
10 | インド | 297,319 | 72,160 | 24.3 | 13,269 | 266.4 | 0.4 | nan |
11 | インドネシア | 187,752 | 92,133 | 49.1 | 4,526 | -752.6 | -0.8 | nan |
... | ... | ... | ... | ... | ... | ... | ... | ... |
このような形になっています。
エクセルの形式からcsvファイルに変換した関係で形式が崩れてしまっています。
Unnamed: 7の列は全てnanで埋まっていることがわかります。
また1行目や2行目にカラムの要素、5行目に単位の情報があり、分析に必要なデータは8行目以降に入っていることが確認できます。
※行数にはインデックスの番号を使用しています。
※他のファイルも大体同じような結果になっています。
分析用のデータを作成するために形式を整える必要があるので、1つずつ実行していきます。
不要なデータの削除
全ての要素がnanになっている列は不要なので、削除します。
natural_area_df1 = natural_area_df1.dropna(how='all', axis=1)
natural_area_df1
1-3 森林の面積(1) | Unnamed: 1 | Unnamed: 2 | Unnamed: 3 | Unnamed: 4 | Unnamed: 5 | Unnamed: 6 | |
---|---|---|---|---|---|---|---|
0 | nan | nan | nan | nan | nan | nan | nan |
1 | 国(地域) | nan | 森林面積(2020年) | nan | nan | 森林面積の純変化 | nan |
2 | nan | 陸地面積 | nan | nan | nan | (2010年~2020年) | nan |
3 | nan | nan | 総面積 | 陸地に占 | 人工林 | 年平均 | 年平均 |
4 | nan | nan | nan | める割合 | nan | nan | 増減率 |
5 | nan | (1,000ha) | (1,000ha) | (%) | (1,000ha) | (1,000ha) | (%) |
6 | nan | nan | nan | nan | nan | nan | nan |
7 | アジア | nan | nan | nan | nan | nan | nan |
8 | 日本 | 36,456 | 24,935 | 68.4 | 10,184 | -3.1 | -0.0 |
9 | イラン | 162,876 | 10,752 | 6.6 | 1,001 | 6.0 | 0.1 |
10 | インド | 297,319 | 72,160 | 24.3 | 13,269 | 266.4 | 0.4 |
11 | インドネシア | 187,752 | 92,133 | 49.1 | 4,526 | -752.6 | -0.8 |
... | ... | ... | ... | ... | ... | ... | ... |
↑Unnamed: 7の列が消えたことがわかります。
8行目以降の必要なデータのある行にはnanは入っていないため、1つでもnanが入っている行は削除します。
natural_area_df1 = natural_area_df1.dropna(how='any', axis=0)
natural_area_df1.reset_index(drop=True, inplace=True)
natural_area_df1
1-3 森林の面積(1) | Unnamed: 1 | Unnamed: 2 | Unnamed: 3 | Unnamed: 4 | Unnamed: 5 | Unnamed: 6 | |
---|---|---|---|---|---|---|---|
0 | 日本 | 36,456 | 24,935 | 68.4 | 10,184 | -3.1 | -0 |
1 | イラン | 162,876 | 10,752 | 6.6 | 1,001 | 6.0 | 0.1 |
2 | インド | 297,319 | 72,160 | 24.3 | 13,269 | 266.4 | 0.4 |
3 | インドネシア | 187,752 | 92,133 | 49.1 | 4,526 | -752.6 | -0.8 |
4 | ウズベキスタン | 42,540 | 3,690 | 8.7 | 2,267 | 34.0 | 1 |
5 | カザフスタン | 269,970 | 3,455 | 1.3 | 421 | 37.3 | 1.2 |
6 | 韓国 | 9,745 | 6,287 | 64.5 | 2,263 | -10.0 | -0.2 |
7 | カンボジア | 17,652 | 8,068 | 45.7 | 604 | -252.1 | -2.7 |
8 | 北朝鮮 | 12,041 | 6,030 | 50.1 | 987 | -21.2 | -0.4 |
9 | タイ | 51,089 | 19,873 | 38.9 | 3,537 | -20.0 | -0.1 |
10 | 中国 a | 942,470 | 219,978 | 23.3 | 84,696 | 1,936.8 | 0.9 |
11 | トルクメニスタン | 46,993 | 4,127 | 8.8 | 0 | 0.0 | 0 |
... | ... | ... | ... | ... | ... | ... | ... |
カラム(列)名の変更
次にカラム(列)名がUnnamedだと分かりにくいので分かりやすい名前に変えていきます。
(元の列名を英語にした名前に変更しています。)
columns = ["country", "land_area", "forest_area", "forest_rate", "artificial_foreat_area", "forest_area_diff", "forest_area_diff_rate"]
natural_area_df1.columns = columns
natural_area_df1
country | land_area | forest_area | forest_rate | artificial_foreat_area | forest_area_diff | forest_area_diff_rate | |
---|---|---|---|---|---|---|---|
0 | 日本 | 36,456 | 24,935 | 68.4 | 10,184 | -3.1 | -0 |
1 | イラン | 162,876 | 10,752 | 6.6 | 1,001 | 6.0 | 0.1 |
2 | インド | 297,319 | 72,160 | 24.3 | 13,269 | 266.4 | 0.4 |
... | ... | ... | ... | ... | ... | ... | ... |
データ削除の関数化
同じことを2つ目のcsvファイル(20240725_world_natural_area2.csv)にも行っていきます。
さっそく進めていきたいところですが、その前に1つ目のファイルで実行した
・要素が全てnanの列を削除
・要素にnanが入っている行を削除
・列名の変更
という処理は今後別のファイルでも実行する予定なので関数としてまとめておきます。
def delete_nan_df(df, columns=None):
"""
全てが欠損値の列を削除
1つでも欠損値のあるデータを削除しindexを振り直す
指定された列名がある場合は列名を変更
"""
df = df.dropna(how='all', axis=1)
df = df.dropna(how='any', axis=0)
df.reset_index(drop=True, inplace=True)
if columns is not None:
df.columns = columns
return df
それでは上で定義した関数も使い2つ目のファイルも扱いやすくしていきます。
file_name = "20240725_world_natural_area2.csv"
data_path = os.path.join(dir_path, file_name)
natural_area_df2 = pd.read_csv(data_path)
columns = ["country", "land_area", "forest_area", "forest_rate", "artificial_forest_area", "forest_area_diff", "forest_area_diff_rate"]
natural_area_df2 = delete_nan_df(natural_area_df2, columns)
natural_area_df2
country | land_area | forest_area | forest_rate | artificial_forest_area | forest_area_diff | forest_area_diff_rate | |
---|---|---|---|---|---|---|---|
0 | イタリア | 29,414 | 9,566 | 32.5 | 645 | 53.8 | 0.6 |
1 | ウクライナ | 57,929 | 9,690 | 16.7 | 4,848 | 14.2 | 0.2 |
2 | オーストリア | 8,252 | 3,899 | 47.3 | 1,672 | 3.6 | 0.1 |
... | ... | ... | ... | ... | ... | ... | ... |
データフレームの結合
最後に2つのデータフレームを結合します。
世界の統計のデータでは注釈などでアルファベットが混ざっているデータもあるのでそれらの文字は削除します。
natural_area_df = pd.concat([natural_area_df1, natural_area_df2], axis=0)
natural_area_df.reset_index(drop=True, inplace=True)
# 余計なアルファベットや記号を削除
natural_area_df = natural_area_df.replace("[a-z*]|\s| |,", "", regex=True)
natural_area_df
country | land_area | forest_area | forest_rate | artificial_forest_area | forest_area_diff | forest_area_diff_rate | |
---|---|---|---|---|---|---|---|
0 | 日本 | 36456 | 24935 | 68.4 | 10184 | -3.1 | -0 |
1 | イラン | 162876 | 10752 | 6.6 | 1001 | 6 | 0.1 |
2 | インド | 297319 | 72160 | 24.3 | 13269 | 266.4 | 0.4 |
... | ... | ... | ... | ... | ... | ... | ... |
84 | パプアニューギニア | 45286 | 35856 | 79.2 | nan | -32.3 | -0.1 |
だいぶ綺麗になりました(^^)
私自身、これで良いと感じていましたが後でよく見てみると、、、
country | land_area | forest_area | forest_rate | artificial_forest_area | forest_area_diff | forest_area_diff_rate | |
---|---|---|---|---|---|---|---|
... | ... | ... | ... | ... | ... | ... | ... |
49 | ドイツ | 34886 | 11419 | 32.7 | 5710 | 1 | 0 |
50 | ノルウェー | 30413 | 12180 | 40 | 108 | 7.8 | 0.1 |
51 | フィンランド | 30391 | 22409 | 73.7 | 7368 | 16.7 | 0.1 |
52 | フランス | 54756 | 17253 | 31.5 | 2434 | 83.4 | 0.5 |
53 | ブルガリア | 10856 | 3893 | 35.9 | 777 | 15.6 | 0.4 |
54 | ベラルーシ | 20298 | 8768 | 43.2 | 2212 | 13.8 | 0.2 |
55 | ポーランド | 30619 | 9483 | 31 | ... | 15.4 | 0.2 |
56 | ポルトガル | 9161 | 3312 | 36.2 | 2256 | 6 | 0.2 |
... | ... | ... | ... | ... | ... | ... | ... |
55 ポーランドの植林のデータが抜けています。
他のサイトで調べて表の単位に換算したところ5570という数値が出てきたので今回はこの値を用います。
natural_area_df.iloc[55, 4] = 5570
natural_area_df[49:56]
country | land_area | forest_area | forest_rate | artificial_forest_area | forest_area_diff | forest_area_diff_rate | |
---|---|---|---|---|---|---|---|
49 | ドイツ | 34886 | 11419 | 32.7 | 5710 | 1 | 0 |
50 | ノルウェー | 30413 | 12180 | 40 | 108 | 7.8 | 0.1 |
51 | フィンランド | 30391 | 22409 | 73.7 | 7368 | 16.7 | 0.1 |
52 | フランス | 54756 | 17253 | 31.5 | 2434 | 83.4 | 0.5 |
53 | ブルガリア | 10856 | 3893 | 35.9 | 777 | 15.6 | 0.4 |
54 | ベラルーシ | 20298 | 8768 | 43.2 | 2212 | 13.8 | 0.2 |
55 | ポーランド | 30619 | 9483 | 31 | 5570 | 15.4 | 0.2 |
56 | ポルトガル | 9161 | 3312 | 36.2 | 2256 | 6 | 0.2 |
ちゃんとデータが入りました(^^)
人口・面積
次は人口・面積のデータです。
各国の人口を調査した年次、人口、特定の年の推計人口などがまとまっています。
(以下、元ページの説明の引用)
2-4 人口・面積
〔出典〕
UN, Demographic Yearbook System, Demographic Yearbook 2022 【参考】データベースの使い方
2023年11月ダウンロード
UN, World Population Prospects:The 2022 Revision 【参考】データベースの使い方
2022年9月ダウンロード〔解説〕
センサス人口:原則として、「現在人口」(de facto population:居住者か非居住者かを問わず、調査時現在その地域に存在する人数)。「常住人口」(de jure population:その地域に通常居住している人数。原則として、国外の自国民を除く。)等の場合は注記した。外国の軍人・外交官及びその家族を除いている国が多い。推計人口:各年7月1日現在。
面積:内水面を含む全面積。極地及び居住不可能な島を除く。
人口密度:面積1平方キロメートル当たりの人口。なお、推計人口とは出典が異なるため、掲載値から算出すると、値が異なる場合がある。
まずは1つ目のデータを読み込んで見てみます。
file_name = "20240725_world_population1.csv"
data_path = os.path.join(dir_path, file_name)
population_df1 = pd.read_csv(data_path)
population_df1
2-4 人口・面積(1) | Unnamed: 1 | Unnamed: 2 | Unnamed: 3 | Unnamed: 4 | Unnamed: 5 | Unnamed: 6 | Unnamed: 7 | Unnamed: 8 | Unnamed: 9 | Unnamed: 10 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
1 | 国(地域) | センサス人口(1,000人) | nan | nan | nan | 推計人口(1,000人) | nan | 面積(km2) | 人口 | nan | nan |
密度 | |||||||||||
2 | nan | 年次 | 総数 | 男 | 女 | 2020 | 2022 | 2022 | 2022 | nan | nan |
3 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
4 | 世界 | nan | - | - | - | 7,840,953 | 7,975,105 | a 130,094,010 | 61 | nan | nan |
5 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
6 | アジア | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
7 | 日本 bc | 20 | 126,146 | 61,350 | 64,797 | 126,146 | 124,947 | 377,973 | 335 | nan | nan |
8 | アゼルバイジャン | 19 | 9,944 | 4,935 | 5,009 | 10,285 | 10,358 | 86,600 | 117 | nan | nan |
9 | アフガニスタン | 79 | d 13,051 | d 6,712 | d 6,339 | 38,972 | 41,129 | 652,864 | 50 | nan | nan |
10 | アラブ首長国連邦 | 5 | 4,106 | 2,806 | 1,300 | 9,287 | 9,441 | a 71,024 | ... | nan | nan |
... | ... | ... | 2,872 | 1,347 | ... | ... | ... | ... | ... | ... | ... |
列名が異なる点以外は大体同じような処理でいけそうです(^^)
列名を適切な名前に変更して同じ処理をしてみます。
columns = ["country", "year", "num", "male_num", "felmale_num", "estimated_num_2020", "estimated_num_2022", "area_2022", "population_density"]
population_df1 = delete_nan_df(population_df1, columns)
population_df1
country | year | num | male_num | felmale_num | estimated_num_2020 | estimated_num_2022 | area_2022 | population_density | |
---|---|---|---|---|---|---|---|---|---|
0 | 日本 bc | 20 | 126,146 | 61,350 | 64,797 | 126,146 | 124,947 | 377,973 | 335 |
1 | アゼルバイジャン | 19 | 9,944 | 4,935 | 5,009 | 10,285 | 10,358 | 86,600 | 117 |
2 | アフガニスタン | 79 | d 13,051 | d 6,712 | d 6,339 | 38,972 | 41,129 | 652,864 | 50 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
残り5つのファイルに対しても同じ処理をします。
その後結合します。
file_name = "20240725_world_population2.csv"
data_path = os.path.join(dir_path, file_name)
population_df2 = pd.read_csv(data_path)
columns = ["country", "year", "num", "male_num", "felmale_num", "estimated_num_2020", "estimated_num_2022", "area_2022", "population_density"]
population_df2 = delete_nan_df(population_df2, columns)
file_name = "20240725_world_population3.csv"
data_path = os.path.join(dir_path, file_name)
population_df3 = pd.read_csv(data_path)
population_df3 = delete_nan_df(population_df3, columns)
... # 4, 5も同様の処理
file_name = "20240725_world_population6.csv"
data_path = os.path.join(dir_path, file_name)
population_df6 = pd.read_csv(data_path)
population_df6 = delete_nan_df(population_df6, columns)
population_df = pd.concat([population_df1, population_df2, population_df3, population_df4, population_df5, population_df6], axis=0)
population_df = population_df.dropna(how='any', axis=0)
population_df.reset_index(drop=True, inplace=True)
population_df = population_df.replace("[a-z*]|\s| |,", "", regex=True)
population_df
country | year | num | male_num | felmale_num | estimated_num_2020 | estimated_num_2022 | area_2022 | population_density | |
---|---|---|---|---|---|---|---|---|---|
0 | 日本 | 20 | 126146 | 61350 | 64797 | 126146 | 124947 | 377973 | 335 |
1 | アゼルバイジャン | 19 | 9944 | 4935 | 5009 | 10285 | 10358 | 86600 | 117 |
2 | アフガニスタン | 79 | 13051 | 6712 | 6339 | 38972 | 41129 | 652864 | 50 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
234 | ワリス・フテュナ諸島 | 18 | 12 | ... | ... | 12 | 12 | 142 | ... |
各国毎のデータがまとまりました(^^)
人口密度(population_density)の列で値が入ってない国がありますがこちらは後ほど対処します。
出生率の推移
次は出生率の推移のデータです。
各国の年毎の出生率がまとまっています。
(以下、元ページの説明の引用)
2-13 出生率の推移
〔出典〕
UN, World Population Prospects : The 2022 Revision 【参考】データベースの使い方
2022年10月ダウンロード〔解説〕
国連人口部による推計値(将来推計は中位推計値)。先進国及び開発途上国の区分については、「2-1 世界人口の推移」の解説を参照。出生率:一定期間の出生数をその期間の人口で割ったもの。一般に、人口1,000人当たりの1年間の出生数で示される。
こちらもほとんど同じような形式のため、今までと同様の処理を行うと、
file_name = "20240725_world_birth_rate.csv"
data_path = os.path.join(dir_path, file_name)
birth_rate_df = pd.read_csv(data_path)
columns = ["country", "1985", "1990", "1995", "2000", "2005", "2010", "2015", "2020", "2025", "2035"]
birth_rate_df = delete_nan_df(birth_rate_df, columns)
birth_rate_df
country | 1985 | 1990 | 1995 | 2000 | 2005 | 2010 | 2015 | 2020 | 2025 | 2035 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 国(地域) | 1985 | 1990 | 1995 | 2000 | 2005 | 2010 | 2015 | 2020 | 2025 | 2035 |
1 | 世界 | 27.9 | 26.8 | 23.3 | 21.8 | 20.7 | 20.3 | 19.2 | 17.2 | 16.4 | 15.5 |
2 | 先進国 | 14.3 | 13.5 | 11.5 | 11.1 | 11.2 | 11.4 | 10.9 | 9.5 | 9.4 | 9.3 |
3 | 開発途上国 | 31.9 | 30.4 | 26.3 | 24.3 | 22.9 | 22.2 | 20.9 | 18.7 | 17.7 | 16.5 |
4 | 日本 | 11.7 | 9.9 | 9.6 | 9.6 | 8.6 | 8.6 | 8 | 6.6 | 6.7 | 7 |
5 | イラン | 41.8 | 32.5 | 20.4 | 16.4 | 16.2 | 17.8 | 19.4 | 14.2 | 12.1 | 10.6 |
6 | インド | 34.6 | 31.8 | 29.4 | 27 | 23.9 | 21.4 | 18.8 | 16.6 | 15.8 | 13.9 |
7 | インドネシア | 29.2 | 25.5 | 23.8 | 21.9 | 20.7 | 20.2 | 18.4 | 16.6 | 15.6 | 14.4 |
8 | 韓国 | 17.3 | 15.7 | 15.3 | 12.5 | 9 | 9.3 | 8.4 | 5.7 | 5.7 | 5.4 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
↑このような形になります(^^;
4 日本の行までは不要なので削除することにします。
また、列名も年だけだと分かりにくいので"country"以外の列名には"birth_rate"という接頭語をつけることにします。(実装では全ての列名に"birth_rate"を頭に付けた後、"birth_rate_country"だけは元の列名("country")に戻しています。)
birth_rate_df = birth_rate_df[4:]
birth_rate_df.reset_index(drop=True, inplace=True)
birth_rate_df = birth_rate_df.replace("[a-z*]|\s| ", "", regex=True)
prefix_str = "birth_rate_"
birth_rate_df = birth_rate_df.add_prefix(prefix_str, axis=1)
birth_rate_df = birth_rate_df.rename(columns={prefix_str + "country": "country"})
birth_rate_df
country | birth_rate_1985 | birth_rate_1990 | birth_rate_1995 | birth_rate_2000 | birth_rate_2005 | birth_rate_2010 | birth_rate_2015 | birth_rate_2020 | birth_rate_2025 | birth_rate_2035 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 日本 | 11.7 | 9.9 | 9.6 | 9.6 | 8.6 | 8.6 | 8 | 6.6 | 6.7 | 7 |
1 | イラン | 41.8 | 32.5 | 20.4 | 16.4 | 16.2 | 17.8 | 19.4 | 14.2 | 12.1 | 10.6 |
2 | インド | 34.6 | 31.8 | 29.4 | 27 | 23.9 | 21.4 | 18.8 | 16.6 | 15.8 | 13.9 |
3 | インドネシア | 29.2 | 25.5 | 23.8 | 21.9 | 20.7 | 20.2 | 18.4 | 16.6 | 15.6 | 14.4 |
4 | 韓国 | 17.3 | 15.7 | 15.3 | 12.5 | 9 | 9.3 | 8.4 | 5.7 | 5.7 | 5.4 |
5 | サウジアラビア | 39.3 | 34.4 | 30 | 27.7 | 23.1 | 21.9 | 19.5 | 18.2 | 15.6 | 13.5 |
6 | タイ | 22.2 | 19.7 | 17.6 | 13.5 | 12.7 | 11.9 | 10.6 | 9.2 | 8.5 | 7.8 |
7 | 中国 | 22.8 | 24.4 | 15.5 | 13.8 | 12.8 | 13.3 | 12.5 | 8.6 | 7.3 | 7.1 |
8 | トルコ | 29.5 | 25.9 | 24 | 21.4 | 18.9 | 17.7 | 17.9 | 15 | 13.6 | 11.7 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
各国毎の出生率の推移をまとめることができました(^^)
死亡率の推移
次は死亡率の推移のデータです。
各国の年毎の死亡率がまとまっています。
(以下、元ページの説明の引用)
2-15 死亡率の推移
〔出典〕
UN, World Population Prospects : The 2022 Revision 【参考】データベースの使い方
2022年10月ダウンロード〔解説〕
国連人口部による推計値(将来推計は中位推計値)。先進国及び開発途上国の区分については「2-1 世界人口の推移」の解説を参照。死亡率:一定期間の死亡数をその期間の人口で割ったもの。一般に、人口1,000人当たりの1年間の死亡数で示される。
形式は上の出生率の推移のデータと同じなのでほとんど同様の処理を行います。(年の列名の接頭語だけ"death_rate"に変更します。)
file_name = "20240725_world_death_rate.csv"
data_path = os.path.join(dir_path, file_name)
death_rate_df = pd.read_csv(data_path)
columns = ["country", "1985", "1990", "1995", "2000", "2005", "2010", "2015", "2020", "2025", "2035"]
death_rate_df = delete_nan_df(death_rate_df, columns)
death_rate_df = death_rate_df[4:]
death_rate_df.reset_index(drop=True, inplace=True)
death_rate_df = death_rate_df.replace("[a-z*]|\s| ", "", regex=True)
prefix_str = "death_rate_"
death_rate_df = death_rate_df.add_prefix(prefix_str, axis=1)
death_rate_df = death_rate_df.rename(columns={prefix_str + "country": "country"})
death_rate_df
country | death_rate_1985 | death_rate_1990 | death_rate_1995 | death_rate_2000 | death_rate_2005 | death_rate_2010 | death_rate_2015 | death_rate_2020 | death_rate_2025 | death_rate_2035 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 日本 | 6.5 | 7 | 7.8 | 8.1 | 9.1 | 10.1 | 11 | 12.1 | 13 | 14.3 |
1 | イラン | 8.8 | 7.2 | 5.5 | 5.2 | 5 | 5.1 | 4.8 | 5.6 | 5.2 | 6.5 |
2 | インド | 12.1 | 10.7 | 9.6 | 8.7 | 7.9 | 7.4 | 6.7 | 7.4 | 6.7 | 7.4 |
3 | インドネシア | 8.9 | 8.1 | 7.5 | 7.4 | 7.3 | 7.4 | 7.5 | 9 | 7.7 | 8.8 |
4 | 韓国 | 6 | 5.3 | 5.3 | 5 | 5.1 | 5.2 | 5.5 | 6.2 | 7.4 | 10 |
5 | サウジアラビア | 6.2 | 4.8 | 4 | 3.5 | 2.9 | 2.5 | 2.5 | 2.9 | 3 | 4.1 |
6 | タイ | 6.2 | 5.6 | 6 | 6 | 6.3 | 6.3 | 6.7 | 7.3 | 7.9 | 9.7 |
7 | 中国 | 7.1 | 7 | 6.3 | 6.2 | 6.2 | 6.5 | 6.8 | 7.3 | 7.8 | 9.7 |
8 | トルコ | 8 | 6.8 | 6.2 | 5.6 | 5.4 | 5.3 | 5.1 | 6.4 | 5.4 | 6.4 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
各国毎の死亡率の推移をまとめることができました(^^)
男女別平均寿命・健康寿命(2019年)
次は男女別平均寿命・健康寿命(2019年)のデータです。
各国の平均寿命・健康寿命がまとまっています。
(以下、元ページの説明の引用)
2-16 男女別平均寿命・健康寿命
〔出典〕
WHO, Global Health Observatory
2022年12月ダウンロード〔解説〕
平均寿命(life expectancy at birth):出生時(0歳)の平均余命(その後生存できると期待される年数)。健康寿命(healthy life expectancy at birth):出生時の健康余命(健康に過ごせると期待される平均的な年数)。健康とは、肉体的・精神的及び社会的に健全な状態をいう。
こちらは他のデータと形式が異なっています。
まずはデータを見てみます。
file_name = "20240725_world_life_expectancy.csv"
data_path = os.path.join(dir_path, file_name)
life_expectancy_df1 = pd.read_csv(data_path)
life_expectancy_df1
2-16 男女別平均寿命・健康寿命(2019年) | Unnamed: 1 | Unnamed: 2 | Unnamed: 3 | Unnamed: 4 | Unnamed: 5 | Unnamed: 6 | Unnamed: 7 | Unnamed: 8 | Unnamed: 9 | Unnamed: 10 | Unnamed: 11 | Unnamed: 12 | Unnamed: 13 | Unnamed: 14 | Unnamed: 15 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | (単位:年) | nan |
1 | 国(地域) | 平均寿命 | nan | nan | 健康寿命 | nan | nan | nan | 国(地域) | 平均寿命 | nan | nan | 健康寿命 | nan | nan | nan |
2 | nan | 男女 | 男 | 女 | 男女 | 男 | 女 | nan | nan | 男女 | 男 | 女 | 男女 | 男 | 女 | nan |
平均 | 平均 | 平均 | 平均 | |||||||||||||
3 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
4 | アジア | nan | nan | nan | nan | nan | nan | nan | アイルランド | 82 | 80 | 83 | 71 | 71 | 71 | nan |
5 | 日本 | 84 | 81 | 87 | 74 | 73 | 75 | nan | イギリス | 81 | 80 | 83 | 70 | 70 | 71 | nan |
6 | アフガニスタン | 63 | 63 | 63 | 54 | 55 | 53 | nan | イタリア | 83 | 81 | 85 | 72 | 71 | 73 | nan |
7 | アラブ首長国連邦 | 76 | 75 | 78 | 66 | 66 | 66 | nan | ウクライナ | 73 | 68 | 78 | 64 | 61 | 68 | nan |
8 | イエメン | 67 | 64 | 69 | 58 | 57 | 58 | nan | オーストリア | 82 | 79 | 84 | 71 | 70 | 72 | nan |
9 | イスラエル | 83 | 81 | 84 | 72 | 72 | 73 | nan | オランダ | 82 | 80 | 83 | 71 | 71 | 72 | nan |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
このデータはUnnamed: 8の列から別の国のデータが入っています。
1行で1つの国のデータにするためには右側のデータと左側のデータに一度分割し、その後に縦に結合する必要があります。
まずは要素が全てnanの列を削除します。
life_expectancy_df1 = life_expectancy_df1.dropna(how='all', axis=1)
life_expectancy_df1
2-16 男女別平均寿命・健康寿命(2019年) | Unnamed: 1 | Unnamed: 2 | Unnamed: 3 | Unnamed: 4 | Unnamed: 5 | Unnamed: 6 | Unnamed: 8 | Unnamed: 9 | Unnamed: 10 | Unnamed: 11 | Unnamed: 12 | Unnamed: 13 | Unnamed: 14 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | (単位:年) |
1 | 国(地域) | 平均寿命 | nan | nan | 健康寿命 | nan | nan | 国(地域) | 平均寿命 | nan | nan | 健康寿命 | nan | nan |
2 | nan | 男女 | 男 | 女 | 男女 | 男 | 女 | nan | 男女 | 男 | 女 | 男女 | 男 | 女 |
平均 | 平均 | 平均 | 平均 | |||||||||||
3 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
4 | アジア | nan | nan | nan | nan | nan | nan | アイルランド | 82 | 80 | 83 | 71 | 71 | 71 |
5 | 日本 | 84 | 81 | 87 | 74 | 73 | 75 | イギリス | 81 | 80 | 83 | 70 | 70 | 71 |
6 | アフガニスタン | 63 | 63 | 63 | 54 | 55 | 53 | イタリア | 83 | 81 | 85 | 72 | 71 | 73 |
7 | アラブ首長国連邦 | 76 | 75 | 78 | 66 | 66 | 66 | ウクライナ | 73 | 68 | 78 | 64 | 61 | 68 |
8 | イエメン | 67 | 64 | 69 | 58 | 57 | 58 | オーストリア | 82 | 79 | 84 | 71 | 70 | 72 |
9 | イスラエル | 83 | 81 | 84 | 72 | 72 | 73 | オランダ | 82 | 80 | 83 | 71 | 71 | 72 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
4 アイルランドのデータのある行までは不要のため削除します。
また列名も変更します。
life_expectancy_df1 = life_expectancy_df1[4:]
life_expectancy_df1.reset_index(drop=True, inplace=True)
columns = ["country", "life_expectancy", "male_life_expectancy", "female_life_expectancy", \
"healthy_life_expectancy", "male_healthy_life_expectancy", "female_healthy_life_expectancy", \
"country", "life_expectancy", "male_life_expectancy", "female_life_expectancy", \
"healthy_life_expectancy", "male_healthy_life_expectancy", "female_healthy_life_expectancy"]
life_expectancy_df1.columns = columns
life_expectancy_df1
country | life_expectancy | male_life_expectancy | female_life_expectancy | healthy_life_expectancy | male_healthy_life_expectancy | female_healthy_life_expectancy | country | life_expectancy | male_life_expectancy | female_life_expectancy | healthy_life_expectancy | male_healthy_life_expectancy | female_healthy_life_expectancy | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | アジア | nan | nan | nan | nan | nan | nan | アイルランド | 82 | 80 | 83 | 71 | 71 | 71 |
1 | 日本 | 84 | 81 | 87 | 74 | 73 | 75 | イギリス | 81 | 80 | 83 | 70 | 70 | 71 |
2 | アフガニスタン | 63 | 63 | 63 | 54 | 55 | 53 | イタリア | 83 | 81 | 85 | 72 | 71 | 73 |
3 | アラブ首長国連邦 | 76 | 75 | 78 | 66 | 66 | 66 | ウクライナ | 73 | 68 | 78 | 64 | 61 | 68 |
4 | イエメン | 67 | 64 | 69 | 58 | 57 | 58 | オーストリア | 82 | 79 | 84 | 71 | 70 | 72 |
5 | イスラエル | 83 | 81 | 84 | 72 | 72 | 73 | オランダ | 82 | 80 | 83 | 71 | 71 | 72 |
6 | イラク | 72 | 70 | 75 | 63 | 62 | 64 | ギリシャ | 81 | 79 | 84 | 71 | 70 | 72 |
7 | イラン | 77 | 76 | 79 | 66 | 66 | 67 | スイス | 83 | 82 | 85 | 73 | 72 | 73 |
8 | インド | 71 | 70 | 72 | 60 | 60 | 60 | スウェーデン | 82 | 81 | 84 | 72 | 72 | 72 |
9 | インドネシア | 71 | 69 | 73 | 63 | 62 | 64 | スペイン | 83 | 81 | 86 | 72 | 71 | 73 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
右側のデータをまとめていきます。
右側のデータに絞った後にnanが入っている行は不要なため削除します。
life_expectancy_df2 = life_expectancy_df1.iloc[:, 7:]
life_expectancy_df2 = life_expectancy_df2.dropna(how='any', axis=0)
life_expectancy_df2.reset_index(drop=True, inplace=True)
life_expectancy_df2
country | life_expectancy | male_life_expectancy | female_life_expectancy | healthy_life_expectancy | male_healthy_life_expectancy | female_healthy_life_expectancy | |
---|---|---|---|---|---|---|---|
0 | アイルランド | 82 | 80 | 83 | 71 | 71 | 71 |
1 | イギリス | 81 | 80 | 83 | 70 | 70 | 71 |
2 | イタリア | 83 | 81 | 85 | 72 | 71 | 73 |
3 | ウクライナ | 73 | 68 | 78 | 64 | 61 | 68 |
4 | オーストリア | 82 | 79 | 84 | 71 | 70 | 72 |
5 | オランダ | 82 | 80 | 83 | 71 | 71 | 72 |
6 | ギリシャ | 81 | 79 | 84 | 71 | 70 | 72 |
7 | スイス | 83 | 82 | 85 | 73 | 72 | 73 |
8 | スウェーデン | 82 | 81 | 84 | 72 | 72 | 72 |
9 | スペイン | 83 | 81 | 86 | 72 | 71 | 73 |
... | ... | ... | ... | ... | ... | ... | ... |
次に左側のデータをまとめます。
右側のデータと同様にnanのある行は削除します。
life_expectancy_df3 = life_expectancy_df1.iloc[:, :7]
life_expectancy_df3 = life_expectancy_df3.dropna(how='any', axis=0)
life_expectancy_df3.reset_index(drop=True, inplace=True)
life_expectancy_df3
country | life_expectancy | male_life_expectancy | female_life_expectancy | healthy_life_expectancy | male_healthy_life_expectancy | female_healthy_life_expectancy | |
---|---|---|---|---|---|---|---|
0 | 日本 | 84 | 81 | 87 | 74 | 73 | 75 |
1 | アフガニスタン | 63 | 63 | 63 | 54 | 55 | 53 |
2 | アラブ首長国連邦 | 76 | 75 | 78 | 66 | 66 | 66 |
3 | イエメン | 67 | 64 | 69 | 58 | 57 | 58 |
4 | イスラエル | 83 | 81 | 84 | 72 | 72 | 73 |
5 | イラク | 72 | 70 | 75 | 63 | 62 | 64 |
6 | イラン | 77 | 76 | 79 | 66 | 66 | 67 |
7 | インド | 71 | 70 | 72 | 60 | 60 | 60 |
8 | インドネシア | 71 | 69 | 73 | 63 | 62 | 64 |
9 | ウズベキスタン | 73 | 71 | 75 | 65 | 64 | 66 |
... | ... | ... | ... | ... | ... | ... | ... |
最後に縦に結合します。
life_expectancy_df = pd.concat([life_expectancy_df3, life_expectancy_df2], axis=0)
life_expectancy_df.reset_index(drop=True, inplace=True)
life_expectancy_df
country | life_expectancy | male_life_expectancy | female_life_expectancy | healthy_life_expectancy | male_healthy_life_expectancy | female_healthy_life_expectancy | |
---|---|---|---|---|---|---|---|
0 | 日本 | 84 | 81 | 87 | 74 | 73 | 75 |
1 | アフガニスタン | 63 | 63 | 63 | 54 | 55 | 53 |
2 | アラブ首長国連邦 | 76 | 75 | 78 | 66 | 66 | 66 |
... | ... | ... | ... | ... | ... | ... | ... |
95 | ニュージーランド | 82 | 80 | 84 | 70 | 70 | 71 |
無事に結合できました(^^)
国内総生産(名目GDP、米ドル表示)
次は国内総生産(名目GDP、米ドル表示)のデータです。
出生率の推移や、死亡率の推移のデータと同じように年毎のGDPがまとまっています。
(以下、元ページの説明の引用)
3-2 国内総生産(名目GDP、米ドル表示)
〔出典〕
UN, National Accounts - Analysis of Main Aggregates (AMA) 【参考】データベースの使い方
2023年9月ダウンロード
こちらは出生率や死亡率のデータを似たような形式になっています。
今までと同様にnanの入っているデータを消して、列名を変更すると、
file_name = "20240725_world_gdp1.csv"
data_path = os.path.join(dir_path, file_name)
gdp_df1 = pd.read_csv(data_path)
columns = ["country", "2005", "2010", "2015", "2017", "2018", "2019", "2020", "2021"]
gdp_df1 = delete_nan_df(gdp_df1, columns)
gdp_df1
country | 2005 | 2010 | 2015 | 2017 | 2018 | 2019 | 2020 | 2021 | |
---|---|---|---|---|---|---|---|---|---|
0 | 国(地域) | 2005 | 2010 | 2015 | 2017 | 2018 | 2019 | 2020 | 2021 |
1 | 世界 | 47,775,404 | 66,578,017 | 75,283,835 | 81,407,118 | 86,601,598 | 87,728,744 | 85,311,030 | 96,698,005 |
2 | 日本 a | 4,834,200 | 5,759,200 | 4,445,400 | 4,931,300 | 5,042,500 | 5,117,900 | 5,048,300 | 5,003,700 |
3 | アラブ首長国連邦 | 182,978 | 289,787 | 358,135 | 385,606 | 422,215 | 417,216 | 357,219 | 405,468 |
4 | イスラエル | 142,657 | 234,655 | 300,078 | 355,277 | 373,641 | 397,935 | 407,101 | 481,591 |
5 | イラク | 49,955 | 138,517 | 166,774 | 187,218 | 227,367 | 233,636 | 180,924 | 204,004 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
このようになります。
2 日本のデータがある行までは不要なので削除します。
gdp_df1 = gdp_df1[2:]
gdp_df1.reset_index(drop=True, inplace=True)
gdp_df1
country | 2005 | 2010 | 2015 | 2017 | 2018 | 2019 | 2020 | 2021 | |
---|---|---|---|---|---|---|---|---|---|
0 | 日本 a | 4,834,200 | 5,759,200 | 4,445,400 | 4,931,300 | 5,042,500 | 5,117,900 | 5,048,300 | 5,003,700 |
1 | アラブ首長国連邦 | 182,978 | 289,787 | 358,135 | 385,606 | 422,215 | 417,216 | 357,219 | 405,468 |
2 | イスラエル | 142,657 | 234,655 | 300,078 | 355,277 | 373,641 | 397,935 | 407,101 | 481,591 |
3 | イラク | 49,955 | 138,517 | 166,774 | 187,218 | 227,367 | 233,636 | 180,924 | 204,004 |
4 | イラン | 228,899 | 523,804 | 417,210 | 503,710 | 526,365 | 519,356 | 543,654 | 594,892 |
5 | インド | 823,612 | 1,669,620 | 2,146,759 | 2,624,329 | 2,763,197 | 2,850,733 | 2,672,204 | 3,201,471 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
2つ目のファイルも同じようにnanの入っているデータを消し、列名を変更すると、
file_name = "20240725_world_gdp2.csv"
data_path = os.path.join(dir_path, file_name)
gdp_df2 = pd.read_csv(data_path)
gdp_df2 = delete_nan_df(gdp_df2, columns)
gdp_df2
country | 2005 | 2010 | 2015 | 2017 | 2018 | 2019 | 2020 | 2021 | |
---|---|---|---|---|---|---|---|---|---|
0 | 国(地域) | 2005 | 2010 | 2015 | 2017 | 2018 | 2019 | 2020 | 2021 |
1 | イギリス | 2,544,813 | 2,491,397 | 2,934,858 | 2,683,399 | 2,878,152 | 2,857,058 | 2,704,609 | 3,131,378 |
2 | イタリア | 1,857,478 | 2,134,018 | 1,835,899 | 1,961,796 | 2,091,932 | 2,011,302 | 1,896,755 | 2,107,703 |
3 | エストニア | 14,104 | 19,535 | 22,882 | 26,924 | 30,625 | 31,082 | 31,370 | 37,191 |
4 | オーストリア | 315,967 | 391,893 | 381,818 | 417,261 | 454,991 | 444,621 | 435,225 | 480,368 |
5 | オランダ | 685,076 | 846,555 | 765,265 | 833,870 | 914,043 | 910,194 | 909,793 | 1,012,847 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
こちらは
1 イギリスのデータがある行までは不要なため削除します。
gdp_df2 = gdp_df2[1:]
gdp_df2.reset_index(drop=True, inplace=True)
gdp_df2
country | 2005 | 2010 | 2015 | 2017 | 2018 | 2019 | 2020 | 2021 | |
---|---|---|---|---|---|---|---|---|---|
1 | イギリス | 2,544,813 | 2,491,397 | 2,934,858 | 2,683,399 | 2,878,152 | 2,857,058 | 2,704,609 | 3,131,378 |
2 | イタリア | 1,857,478 | 2,134,018 | 1,835,899 | 1,961,796 | 2,091,932 | 2,011,302 | 1,896,755 | 2,107,703 |
3 | エストニア | 14,104 | 19,535 | 22,882 | 26,924 | 30,625 | 31,082 | 31,370 | 37,191 |
4 | オーストリア | 315,967 | 391,893 | 381,818 | 417,261 | 454,991 | 444,621 | 435,225 | 480,368 |
5 | オランダ | 685,076 | 846,555 | 765,265 | 833,870 | 914,043 | 910,194 | 909,793 | 1,012,847 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
最後に2つの結合して不要な文字を削除し、country以外の列名の頭に"gdp_"を追加します。
gdp_df = pd.concat([gdp_df1, gdp_df2], axis=0)
gdp_df = gdp_df.replace("[a-z*]|\s| |,", "", regex=True)
prefix_str = "gdp_"
gdp_df = gdp_df.add_prefix(prefix_str, axis=1)
gdp_df = gdp_df.rename(columns={prefix_str + "country": "country"})
gdp_df
country | gdp_2005 | gdp_2010 | gdp_2015 | gdp_2017 | gdp_2018 | gdp_2019 | gdp_2020 | gdp_2021 | |
---|---|---|---|---|---|---|---|---|---|
0 | 日本 | 4834200 | 5759200 | 4445400 | 4931300 | 5042500 | 5117900 | 5048300 | 5003700 |
1 | アラブ首長国連邦 | 182978 | 289787 | 358135 | 385606 | 422215 | 417216 | 357219 | 405468 |
2 | イスラエル | 142657 | 234655 | 300078 | 355277 | 373641 | 397935 | 407101 | 481591 |
3 | イラク | 49955 | 138517 | 166774 | 187218 | 227367 | 233636 | 180924 | 204004 |
4 | イラン | 228899 | 523804 | 417210 | 503710 | 526365 | 519356 | 543654 | 594892 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
40 | ニュージーランド | 114722 | 146518 | 178064 | 206624 | 211953 | 213435 | 212214 | 250451 |
GDPのデータもまとまりました(^^)
テーブルデータの作成
ここまででそれぞれのデータの整形を終えました。国ごとのデータを作成したいので最後にcountryをキーにしてマージします。単純にデータフレームを1つずつマージしても良いのですが、今後様々なパターンでマージできるようにするために少し工夫します。
まずそれぞれのデータフレームをまとめたdictを用意します。
df_dict = {
"natural_area": natural_area_df,
"population": population_df,
"birth_rate": birth_rate_df,
"death_rate": death_rate_df,
"life_expectancy": life_expectancy_df,
"gdp": gdp_df,
}
そしてマージするか否かを設定するdictを用意します。今回は全てマージするものとして全てTrueで設定しておきます。
merge_setting_dict = {
"natural_area": True,
"population": True,
"birth_rate": True,
"death_rate": True,
"life_expectancy": True,
"gdp": True,
}
設定dictの値に応じてマージする関数を定義します。
def generate_country_df(df_dict, setting_dict):
"""
設定dictに応じてdf_dict内のデータフレームをcountryをキーにしてマージする。
Parameters
----------
df_dict: データ名とデータフレームを紐づけたdict
setting_dict: データ名とmergeするか否かを設定したdict
Returns
----------
merged_df: マージ後のデータフレーム
"""
merged_df = pd.DataFrame()
for data_name, df in df_dict.items():
# 設定でTrueになっている場合
if setting_dict[data_name]:
# 最初のdfの場合はそのdfをmerged_dfにする
if len(merged_df) == 0:
merged_df = df
# すでにmerged_dfがある場合はmergeして更新
else:
merged_df = pd.merge(merged_df, df, on="country")
return merged_df
実際にマージすると
data = generate_country_df(df_dict, merge_setting_dict)
data
country | land_area | forest_area | forest_rate | artificial_forest_area | forest_area_diff | forest_area_diff_rate | year | num | male_num | felmale_num | estimated_num_2020 | estimated_num_2022 | area_2022 | population_density | birth_rate_1985 | birth_rate_1990 | birth_rate_1995 | birth_rate_2000 | birth_rate_2005 | birth_rate_2010 | birth_rate_2015 | birth_rate_2020 | birth_rate_2025 | birth_rate_2035 | death_rate_1985 | death_rate_1990 | death_rate_1995 | death_rate_2000 | death_rate_2005 | death_rate_2010 | death_rate_2015 | death_rate_2020 | death_rate_2025 | death_rate_2035 | gdp_2005 | gdp_2010 | gdp_2015 | gdp_2017 | gdp_2018 | gdp_2019 | gdp_2020 | gdp_2021 | life_expectancy | male_life_expectancy | female_life_expectancy | healthy_life_expectancy | male_healthy_life_expectancy | female_healthy_life_expectancy | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 日本 | 36456 | 24935 | 68.4 | 10184 | -3.1 | -0 | 20 | 126146 | 61350 | 64797 | 126146 | 124947 | 377973 | 335 | 11.7 | 9.9 | 9.6 | 9.6 | 8.6 | 8.6 | 8 | 6.6 | 6.7 | 7 | 6.5 | 7 | 7.8 | 8.1 | 9.1 | 10.1 | 11 | 12.1 | 13 | 14.3 | 4834200 | 5759200 | 4445400 | 4931300 | 5042500 | 5117900 | 5048300 | 5003700 | 84 | 81 | 87 | 74 | 73 | 75 |
1 | イラン | 162876 | 10752 | 6.6 | 1001 | 6 | 0.1 | 16 | 79926 | 40498 | 39428 | 87290 | 88551 | 1630848 | 52 | 41.8 | 32.5 | 20.4 | 16.4 | 16.2 | 17.8 | 19.4 | 14.2 | 12.1 | 10.6 | 8.8 | 7.2 | 5.5 | 5.2 | 5 | 5.1 | 4.8 | 5.6 | 5.2 | 6.5 | 228899 | 523804 | 417210 | 503710 | 526365 | 519356 | 543654 | 594892 | 77 | 76 | 79 | 66 | 66 | 67 |
2 | インド | 297319 | 72160 | 24.3 | 13269 | 266.4 | 0.4 | 11 | 1210855 | 623270 | 587585 | 1396387 | 1417173 | 3287263 | ... | 34.6 | 31.8 | 29.4 | 27 | 23.9 | 21.4 | 18.8 | 16.6 | 15.8 | 13.9 | 12.1 | 10.7 | 9.6 | 8.7 | 7.9 | 7.4 | 6.7 | 7.4 | 6.7 | 7.4 | 823612 | 1669620 | 2146759 | 2624329 | 2763197 | 2850733 | 2672204 | 3201471 | 71 | 70 | 72 | 60 | 60 | 60 |
3 | インドネシア | 187752 | 92133 | 49.1 | 4526 | -752.6 | -0.8 | 20 | 270204 | 136662 | 133542 | 271858 | 275501 | 1910931 | 144 | 29.2 | 25.5 | 23.8 | 21.9 | 20.7 | 20.2 | 18.4 | 16.6 | 15.6 | 14.4 | 8.9 | 8.1 | 7.5 | 7.4 | 7.3 | 7.4 | 7.5 | 9 | 7.7 | 8.8 | 304372 | 755094 | 860854 | 1015619 | 1042272 | 1119100 | 1058689 | 1186093 | 71 | 69 | 73 | 63 | 62 | 64 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
31 | ニュージーランド | 26331 | 9893 | 37.6 | 2084 | 4.4 | 0.1 | 18 | 4793 | 2364 | 2429 | 5061 | 5185 | 268107 | ... | 15.9 | 17.8 | 15.6 | 14.7 | 13.9 | 14.6 | 13.1 | 12.5 | 12 | 10.6 | 8.4 | 7.9 | 7.6 | 6.9 | 6.6 | 6.6 | 6.6 | 6.4 | 6.9 | 8.1 | 114722 | 146518 | 178064 | 206624 | 211953 | 213435 | 212214 | 250451 | 82 | 80 | 84 | 70 | 70 | 71 |
このようになります。
ちゃんとマージできてそうです。
次に使用する列を絞っていきます。
今回は値が入ってない列(nanは省いていたが"..."という値が入っている列が残っている)、2015年より前の列、2025年以降の列を省きます。
using_df_columns = [
# 国
'country',
# 陸地と森
'land_area', 'forest_area', 'forest_rate',
'artificial_forest_area', 'forest_area_diff', 'forest_area_diff_rate',
# 人口
'num',
'estimated_num_2020', 'estimated_num_2022',
# 出生率
'birth_rate_2015', 'birth_rate_2020',
# 死亡率
'death_rate_2015', 'death_rate_2020',
# 寿命
'life_expectancy', 'male_life_expectancy', 'female_life_expectancy',
'healthy_life_expectancy', 'male_healthy_life_expectancy', 'female_healthy_life_expectancy',
# GDP
'gdp_2015', 'gdp_2017', 'gdp_2018', 'gdp_2019', 'gdp_2020', 'gdp_2021',
]
using_df = data[using_df_columns]
using_df
country | land_area | forest_area | forest_rate | artificial_forest_area | forest_area_diff | forest_area_diff_rate | num | estimated_num_2020 | estimated_num_2022 | birth_rate_2015 | birth_rate_2020 | death_rate_2015 | death_rate_2020 | gdp_2015 | gdp_2017 | gdp_2018 | gdp_2019 | gdp_2020 | gdp_2021 | life_expectancy | male_life_expectancy | female_life_expectancy | healthy_life_expectancy | male_healthy_life_expectancy | female_healthy_life_expectancy | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 日本 | 36456 | 24935 | 68.4 | 10184 | -3.1 | -0 | 126146 | 126146 | 124947 | 8 | 6.6 | 11 | 12.1 | 4445400 | 4931300 | 5042500 | 5117900 | 5048300 | 5003700 | 84 | 81 | 87 | 74 | 73 | 75 |
1 | イラン | 162876 | 10752 | 6.6 | 1001 | 6 | 0.1 | 79926 | 87290 | 88551 | 19.4 | 14.2 | 4.8 | 5.6 | 417210 | 503710 | 526365 | 519356 | 543654 | 594892 | 77 | 76 | 79 | 66 | 66 | 67 |
2 | インド | 297319 | 72160 | 24.3 | 13269 | 266.4 | 0.4 | 1210855 | 1396387 | 1417173 | 18.8 | 16.6 | 6.7 | 7.4 | 2146759 | 2624329 | 2763197 | 2850733 | 2672204 | 3201471 | 71 | 70 | 72 | 60 | 60 | 60 |
3 | インドネシア | 187752 | 92133 | 49.1 | 4526 | -752.6 | -0.8 | 270204 | 271858 | 275501 | 18.4 | 16.6 | 7.5 | 9 | 860854 | 1015619 | 1042272 | 1119100 | 1058689 | 1186093 | 71 | 69 | 73 | 63 | 62 | 64 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
31 | ニュージーランド | 26331 | 9893 | 37.6 | 2084 | 4.4 | 0.1 | 4793 | 5061 | 5185 | 13.1 | 12.5 | 6.6 | 6.4 | 178064 | 206624 | 211953 | 213435 | 212214 | 250451 | 82 | 80 | 84 | 70 | 70 | 71 |
人口密度の列には値が入っていない国があったので省きましたが、人口と陸地の面積があるので計算して追加します。人口密度は人数を平方キロメートルで割った値で定義されています。現状のデータでは、陸地の面積が1000ha, 人数が1000人単位の値になっているので単位を合わせて計算します。
# ヘクタールを平方kmに直す
using_df.loc[:, "land_area"] = using_df.loc[:, "land_area"] * 1000 * (1/100)
using_df.loc[:, "forest_area"] = using_df.loc[:, "forest_area"] * 1000 * (1/100)
using_df.loc[:, "artificial_forest_area"] = using_df.loc[:, "artificial_forest_area"] * 1000 * (1/100)
# 人数の単位を人にする
using_df.loc[:, "estimated_num_2020"] = using_df.loc[:, "estimated_num_2020"] * 1000
# 人口密度の人数を2020の推定人口にする
using_df.loc[:, "population_density"] = using_df.loc[:, "estimated_num_2020"] / using_df.loc[:, "land_area"]
using_df
country | land_area | forest_area | forest_rate | artificial_forest_area | forest_area_diff | forest_area_diff_rate | num | estimated_num_2020 | estimated_num_2022 | birth_rate_2015 | birth_rate_2020 | death_rate_2015 | death_rate_2020 | gdp_2015 | gdp_2017 | gdp_2018 | gdp_2019 | gdp_2020 | gdp_2021 | life_expectancy | male_life_expectancy | female_life_expectancy | healthy_life_expectancy | male_healthy_life_expectancy | female_healthy_life_expectancy | population_density | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 日本 | 364560 | 249350 | 68.4 | 101840 | -3.1 | -0 | 126146 | 1.26146e+08 | 124947 | 8 | 6.6 | 11 | 12.1 | 4.4454e+06 | 4.9313e+06 | 5.0425e+06 | 5.1179e+06 | 5.0483e+06 | 5.0037e+06 | 84 | 81 | 87 | 74 | 73 | 75 | 346.023 |
1 | イラン | 1.62876e+06 | 107520 | 6.6 | 10010 | 6 | 0.1 | 79926 | 8.729e+07 | 88551 | 19.4 | 14.2 | 4.8 | 5.6 | 417210 | 503710 | 526365 | 519356 | 543654 | 594892 | 77 | 76 | 79 | 66 | 66 | 67 | 53.5929 |
2 | インド | 2.97319e+06 | 721600 | 24.3 | 132690 | 266.4 | 0.4 | 1.21086e+06 | 1.39639e+09 | 1.41717e+06 | 18.8 | 16.6 | 6.7 | 7.4 | 2.14676e+06 | 2.62433e+06 | 2.7632e+06 | 2.85073e+06 | 2.6722e+06 | 3.20147e+06 | 71 | 70 | 72 | 60 | 60 | 60 | 469.66 |
3 | インドネシア | 1.87752e+06 | 921330 | 49.1 | 45260 | -752.6 | -0.8 | 270204 | 2.71858e+08 | 275501 | 18.4 | 16.6 | 7.5 | 9 | 860854 | 1.01562e+06 | 1.04227e+06 | 1.1191e+06 | 1.05869e+06 | 1.18609e+06 | 71 | 69 | 73 | 63 | 62 | 64 | 144.796 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
31 | ニュージーランド | 263310 | 98930 | 37.6 | 20840 | 4.4 | 0.1 | 4793 | 5.061e+06 | 5185 | 13.1 | 12.5 | 6.6 | 6.4 | 178064 | 206624 | 211953 | 213435 | 212214 | 250451 | 82 | 80 | 84 | 70 | 70 | 71 | 19.2207 |
1つのテーブルデータとしてまとめることができました(^^)
最終的に32×27のデータフレームになりました。
後書き
色々なデータを組み合わせた結果、結構面白いデータになっていると思います。
次回はこのデータフレームのcountry以外の列を使用して主成分分析を行なっていきます。
末筆ながら今回利用した世界の統計データをオープンデータとして提供してくださっている総務省統計局の皆様に改めて感謝申し上げますm(_ _)m
参考
・データクレンジングで使えるコマンド関連
・正規表現
Discussion