制作世界人口地圖:JSON格式


1.提取2010世界人口數據

先查看json文件數據:

這個文件實際上就是一個很長的Python列表,其中每個元素都是一個包含四個鍵的字典:國家名、國別嗎、年份以及表示人口數量的值。

我們嘗試打印每個國家2010年的人口數量:

import json

filename="population_data.json"
with open(filename) as f:
    pop_data=json.load(f)
    
for pop_dict in pop_data:
    if pop_dict['Year']=='2010':
        country_name=pop_dict['Country Name']
        population=pop_dict['Value']
        print(country_name+': '+population)

接下來,我們要將數據轉化為Pygal能夠處理的格式。

 

2.將字符串轉化為數字值

Python不能直接將包含小數點的字符串轉化為整數,為消除這種錯誤我們可以先將字符串轉換為浮點數,再講浮點數轉換為小數:

population=int(float(pop_dict['Value']))
print(country_name+': '+str(population))

可以發現High income的小數被丟棄了。

 

3.獲取兩個字母的國別碼

Pygal中的地圖制作工具要求數據為特定的格式:用國別碼表示國家,以及用數字表示人口數量。

因為Pygal使用兩個字母的國別碼,所以我們需要想辦法根據國家名獲取兩個字母的國別碼。

字典COUNTRIES包含的鍵值分別為兩個字母的國別碼和國家名,我們可以從模塊i18n中導入這個字典,並打印其鍵和值:

from pygal_maps_world.i18n import COUNTRIES

for country_code in sorted(COUNTRIES.keys()):
    print(country_code,COUNTRIES[country_code])

 

編寫一個獲取國別碼的函數放在名為country_codes的模塊中:

from pygal_maps_world.i18n import COUNTRIES

def get_country_code(country_name):
    for code,name in COUNTRIES.items():
        if name==country_name:
            return code
    return None

 

修改打印人口數量的代碼:

import json

from country_codes import get_country_code

filename="population_data.json"
with open(filename) as f:
    pop_data=json.load(f)
    
for pop_dict in pop_data:
    if pop_dict['Year']=='2010':
        country_name=pop_dict['Country Name']
        population=int(float(pop_dict['Value']))
        code=get_country_code(country_name)
        if code:
            print(code + ': '+str(population))
        else:
            print('ERROR - ' + country_name)

導致顯示錯誤消息的原因有兩個。首先並非所有人口數量對應的都是國家,有些人口數量對應的是地區(阿拉伯世界)和經濟類群(所有收入水平),其次有些統計數據使用了不同的完整國家名。

 

4.制作世界地圖

import pygal.maps.world

wm = pygal.maps.world.World()
wm.title = 'North, Central, and South America'

wm.add('North America', ['ca', 'mx', 'us'])
wm.add('Central America', ['bz', 'cr', 'gt', 'hn', 'ni', 'pa', 'sv'])
wm.add('South America', ['ar', 'bo', 'br', 'cl', 'co', 'ec', 'gf',
    'gy', 'pe', 'py', 'sr', 'uy', 've'])
    
wm.render_to_file('americas.svg')

方法add()接受一個標簽和一個列表,其中后者包含我們要突出的國家的國別碼。

每次調用用add()都將為指定的國家選擇一種新顏色,並在圖表左邊顯示該顏色和指定的標簽。

 

 

5.繪制完整的世界人口地圖

import json

import pygal.maps.world

from country_codes import get_country_code

filename="population_data.json"
with open(filename) as f:
    pop_data=json.load(f)
    
cc_populations={}
for pop_dict in pop_data:
    if pop_dict['Year']=='2010':
        country_name=pop_dict['Country Name']
        population=int(float(pop_dict['Value']))
        code=get_country_code(country_name)
        if code:
            cc_populations[code]=population
            
wm=pygal.maps.world.World()
wm.title="World Population in 2010,by Country"
wm.add('2010',cc_populations)

wm.render_to_file('World_population.svg')

有幾個國家沒有相關數據,我們將其顯示為白色,但對於大多數國家,都根據其人口數量進行了着色。

當前地圖中,很多國家都是淺色的,只有兩個國家是深色的。對大多數國家而言,顏色深淺差別不足以反映其人口數量的差別。

為修復這種問題,我們將根據人口數量將國家分組,再分別對每個組着色:

cc_pops_1,cc_pops_2,cc_pops_3={},{},{}
for cc,pop in cc_populations.items():
    if pop<10000000:
        cc_pops_1[cc]=pop
    elif pop<100000000:
        cc_pops_2[cc]=pop
    else:
        cc_pops_3[cc]=pop

 

6.使用Pygal設置世界地圖的樣式

我們從模塊中導入了樣式RotateStyle,創建這個實例時,需要提供一個參數--十六進制的RGB顏色。

十六進制格式的RGB顏色是一個以井號(#)打頭的字符串,后面跟着6個字符,其中前兩個表示紅色分量,接下來是綠色和藍色。

這里使用的顏色值(#336699)混合了少量的紅色(33)、多一些的綠色(66)和更多一些的藍色(99),它為RotateStyle提供了一種淡藍色基色。

 

加亮顏色主題

Pygal通常默認使用較暗的顏色主題,為方便印刷,我們使用LightColorizedStyle加亮了地圖顏色。

這個類修改整個圖表的主題,包括背景色、標簽以及各個國家的顏色:

from pygal.style import LightColorizedStyle

wm_style=LightColorizedStyle

使用這個類時,不能直接控制使用的顏色,Pygal將選擇默認的基色,要設置顏色,可使用RotateStyle,並將LightColorizedStyle作為基本樣式。

 

完整代碼:

import json

import pygal.maps.world
from pygal.style import RotateStyle,LightColorizedStyle

from country_codes import get_country_code

filename="population_data.json"
with open(filename) as f:
    pop_data=json.load(f)
    
cc_populations={}
for pop_dict in pop_data:
    if pop_dict['Year']=='2010':
        country_name=pop_dict['Country Name']
        population=int(float(pop_dict['Value']))
        code=get_country_code(country_name)
        if code:
            cc_populations[code]=population
            
cc_pops_1,cc_pops_2,cc_pops_3={},{},{}
for cc,pop in cc_populations.items():
    if pop<10000000:
        cc_pops_1[cc]=pop
    elif pop<100000000:
        cc_pops_2[cc]=pop
    else:
        cc_pops_3[cc]=pop
        
print(len(cc_pops_1),len(cc_pops_2),len(cc_pops_3))

wm_style=RotateStyle('#336699',base_style=LightColorizedStyle)            
wm=pygal.maps.world.World(style=wm_style)
wm.title="World Population in 2010,by Country"
wm.add('0-10m',cc_pops_1)
wm.add('10m-1bn',cc_pops_2)
wm.add('>1bn',cc_pops_3)

wm.render_to_file('World_population.svg')

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM