読者です 読者をやめる 読者になる 読者になる

GIS奮闘記

現役GISエンジニアの技術紹介ブログ。主にPythonを使用。

【ArcMapとArcpy】オープンデータを使って自分だけの地図を作ろう! ~factbook編~

今回はfactbookを使用してみようと思います。factbookとは世界各国に関する情報を年鑑形式でまとめたアメリカ合衆国中央情報局 (CIA) の年次刊行物のことです。こんな便利なものが公開されているのですね。

ダウンロード

以下サイトからダウンロードします。JSONファイルです。
factbook/factbook.json: World Factbook Coun... - GitHub

JSONなのでこんな感じですね。項目一覧が無いので、欲しい情報がどれなのか一つ一つ項目を確認しなければならないのがちょっとしんどいですね。
f:id:sanvarie:20160119112336p:plain

サンプルコード

今回はその国の人口における65歳以上の割合、普通出生率GDP($)を取得したいと思います。普通出生率とは日本で一般的な合計特殊出生率ではなく、人口1000人あたりにおける出生数らしいです。まずはJSONのデータを取得するサンプルです。

# -*- coding: utf-8 -*-
import json
from os.path import join,relpath
from glob import glob
import pandas as pd

#ダウンロードしたフォルダのパスを指定
path = r"D:\python\factbook\factbook.json-master"

dataList = []

#各大陸のフォルダをループ
for fs in [relpath(x,path) for x in glob(join(path,'*'))]:
    #フォルダの場合
    if fs.find('.') == -1:
        folder = join(path , fs)
        #フォルダ内のjsonファイルをループ
        for js in [relpath(x,folder) for x in glob(join(folder,'*'))]:
            if js != "xx.json":
                #jsonファイルを開く
                with open(join(folder , js), "r") as f:
                    #ロード
                    jsonData = json.load(f)
                    #ここから階層をくだっていく
                    for name in jsonData.keys():
                        groupDict = jsonData[name]
                        if name == "Government":
                            #この下のキーでループ
                            for name2 in groupDict.keys():
                                groupDict2 =  groupDict[name2]
                                if name2 == "Country name":
                                    #この下のキーでループ
                                    for name3 in groupDict2.keys():
                                        groupDict3 =  groupDict2[name3]
                                        if name3 == "conventional short form":
                                            #この下のキーでループ
                                            for name4 in groupDict3.keys():
                                                groupDict4 =  groupDict3[name4]
                                                if name4 == "text":
                                                    counryName = groupDict4 + ","
                        elif name == "People and Society":
                            #この下のキーでループ
                            for name2 in groupDict.keys():
                                groupDict2 =  groupDict[name2]
                                if name2 == "Age structure":
                                    #この下のキーでループ
                                    for name3 in groupDict2.keys():
                                        groupDict3 =  groupDict2[name3]
                                        #65歳以上の割合
                                        if name3 == "65 years and over":
                                            #この下のキーでループ
                                            for name4 in groupDict3.keys():
                                                groupDict4 =  groupDict3[name4]
                                                if name4 == "text":
                                                    overSixtyFive = groupDict4[0:groupDict4.find("%")] + ","
                                #普通出生率
                                elif name2 == "Birth rate":
                                    for name3 in groupDict2.keys():
                                        groupDict3 =  groupDict2[name3]
                                        if name3 == "text":
                                            birthRate = groupDict3[0:groupDict3.find(" births")] + ","
                        elif name == "Economy":
                            #この下のキーでループ
                            for name2 in groupDict.keys():
                                groupDict2 =  groupDict[name2]
                                #GDP($)
                                if name2 == "GDP (official exchange rate)":
                                    #この下のキーでループ
                                    for name3 in groupDict2.keys():
                                        groupDict3 =  groupDict2[name3]
                                        if name3 == "text":
                                            if groupDict3.find(' million') != -1:
                                                GDP = str(float(groupDict3[1:groupDict3.find(" million")]) * 1000000)
                                            elif groupDict3.find(' billion') != -1:
                                                GDP = str(float(groupDict3[1:groupDict3.find(" billion")]) * 1000000000)
                                            elif groupDict3.find(' trillion') != -1:
                                                GDP = str(float(groupDict3[1:groupDict3.find(" trillion")]) * 1000000000000)
                                            else:
                                                GDP = "0"

                dataList.append([counryName,overSixtyFive,birthRate,GDP])

            #データフレーム作成
            df = pd.DataFrame(dataList)
            df.columns = [u"counryName",u"overSixtyFive",u"birthRate","GDP"]

factbookを世界地図に反映

以前使用した世界地図を用意します。

f:id:sanvarie:20160119120535p:plain

まず、このレイヤにカラム追加します。

arcpy.AddField_management("TM_WORLD_BORDERS-0.3", "overSF", "Double")
arcpy.AddField_management("TM_WORLD_BORDERS-0.3", "birthRate", "Double")
arcpy.AddField_management("TM_WORLD_BORDERS-0.3", "GDP", "Double")

こんな感じになったら成功です。
f:id:sanvarie:20160119132039p:plain

次にJSONから取得した値をフィーチャの属性に反映させます。

for key,rowD in df.iterrows():
    cursorJ = arcpy.UpdateCursor("TM_WORLD_BORDERS-0.3")
    for rowJ in cursorJ:
        #国名が微妙に異なるのはとりあえず無視(GambiaとThe Gambiaとか)
        if rowD.counryName == rowJ.NAME:
            rowJ.setValue("overSF", rowD.overSixtyFive)
            rowJ.setValue("birthRate", rowD.birthRate)
            rowJ.setValue("GDP", rowD.GDP)
            cursorJ.updateRow(rowJ)

こんな感じになったら成功です。
f:id:sanvarie:20160119132959p:plain

分析

データもそろったので分析をしてみたいと思います。

人口における65歳以上の割合

レイヤの設定を以下のようにします。
f:id:sanvarie:20160119133436p:plain

やはりわが日本が厳しい状態ですね。ヨーロッパ、カナダなどの先進国は高齢化していて、その反面、アフリカや南アジアなどの新興国は高齢者の割合が低いことが分かりました(アフリカなどは平均寿命の関係もありそうですが)。
f:id:sanvarie:20160119134215p:plain

普通出生率

前述した通り、普通出生率とは日本で一般的な合計特殊出生率ではなく、人口1000人あたりにおける出生数らしいです。

レイヤの設定を以下のようにします。
f:id:sanvarie:20160119133725p:plain

これもわが日本を含め先進国は厳しい状態ですね。
f:id:sanvarie:20160119133845p:plain

GDP($)

レイヤの設定を以下のようにします。
f:id:sanvarie:20160119134353p:plain

GDPはアメリカと中国が突出していて、次に日本を含めた先進国が高いという結果が出ました。まぁこれはみなさんよくご存知かもしれませんね。また、アフリカ、東欧、東南アジアに今後の伸びしろがあるのがわかります。東南アジア経済は今熱いですしね!
f:id:sanvarie:20160119135727p:plain

今回は65歳以上の割合、普通出生率GDP($)のデータを使用しましたが、factbookにはその他にもたくさんのデータがあります。例えば、エネルギー、軍事、経済、政治などですね。これらをうまく活用すれば世界を色々な視点から分析することが可能になりますね。

以上、「【ArcMapとArcpy】オープンデータを使って自分だけの地図を作ろう! ~factbook編~」でした。