Python下绘制世界人口地图
小弟最近抽空学了学python,一直看到各位大神用python绘制的各种数据图表我都能是羡慕啊,这次就自己学着做了张世界地图,不足之处多多指正
/***************************************************神奇分割线************************************************/
一、获取数据
要做世界地图首先得有世界人口数据吧,我从这里下的:http://data.okfn.org/,获取到JSON格式的人口文件后先写一个简单的解析JSON内容的.py吧
world_population.py
import json
# 将数据加载到一个列表中
filename = 'population_data.json'
with open(filename) as f:
pop_data = json.load(f)
# 打印每个国家2018年的人口数量
for pop_dict in pop_data:
if pop_dict['Year'] == '2018':
country_name = pop_dict['Country Name']
population = pop_dict['Value']
print(country_name + ": " + population)
看到结果就是解析出的2018人口数据啦:
Arab World: 357868000
Caribbean small states: 6880000
East Asia & Pacific (all income levels): 2201536674
--snip--
Zimbabwe: 12571000
二、加工数据
人口是个数字值,我们看到里面有些数值是小数形式的,那么转成整数值就要多一步
--snip--
for pop_dict in pop_data:
if pop_dict['Year'] == '2010':
country = pop_dict['Country Name']
population = int(float(pop_dict['Value']))
print(country + ": " + str(population))
Pygal中的地图制作工具要求数据为特定的格式:用国别码表示国家,以及用数字表示人口数量,这里又要转换一下国别码了
我们先查看一下在pygal.maps.world包中的国别码格式:
country_codes.py
#导入世界地图包pygal_maps_world
import pygal.maps.world
# 定义函数,返回适用于pygal的两位国别码
def get_country_code(country_name):
# pygal两位国别码列表表示法:pygal.maps.world.COUNTRIES.items()
for code,name in pygal.maps.world.COUNTRIES.items():
if name == country_name:
return code
return None
接下来根据JSON中的国家名取出相应的国别码:
import json
from country_codes import get_country_code
--snip--
# 打印每个国家2018年的人口数量
for pop_dict in pop_data:
if pop_dict['Year'] == '2018':
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)
三、显示图表
数据都有啦,接下来要使用python的pygal提供World图表类型绘制地图,下面是个查看美洲地图的示例
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'])
#保存为svg格式查看
wm.render_to_file('americas.svg')
用浏览器打开下方生成的svg格式,就可以看到一个简单的图表啦
是不是已经有点样子了呢,那么我们就要把人口数据加上图表去并给人口划分一个范围来绘制
import pygal.maps.world
wm = pygal.Worldmap()
wm.title = 'Populations of Countries in North America'
#添加以人口数据为底的实例
wm.add('North America', {'ca': 34126000, 'us': 309349000, 'mx': 113423000})
wm.render_to_file('na_populations.svg')
这时打开svg就可以在相应位置看到弹出人口信息
完善一下世界人口.py
import json
import pygal.maps.world
from country_codes import get_country_code
# 将数据加载到列表中
--snip--
# 创建一个包含人口数量的字典
cc_populations = {}
for pop_dict in pop_data:
if pop_dict['Year'] == '2018':
country = pop_dict['Country Name']
population = int(float(pop_dict['Value']))
code = get_country_code(country)
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 < 1000000000:
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 = pygal.maps.world.World()
wm.title = 'World Population in 2018, 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')
四、让图表更直观
我们成功让世界人口数据在世界地图上显示了出来,现在就要让数据更加容易理解和美观,这里要使用pygal设置样式
import json
import pygal.maps.world
from pygal.style import RotateStyle
--snip--
# 根据人口数量将所有的国家分成三组
cc_pops_1, cc_pops_2, cc_pops_3 = {}, {}, {}
for cc, pop in cc_populations.items():
if pop < 10000000:
--snip--
wm_style = RotateStyle('#336699')
wm = pygal.maps.world.World(style=wm_style)
wm.title = 'World Population in 2018, by Country'
--snip--
这时已经可以看到不同范围的人口地图被分成了一块一块的颜色了,Pygal通常默认使用较暗的颜色主题。为方便印刷,要使用LightColorizedStyle加亮地图
import json
--snip--
from pygal.style import LightColorizedStyle, RotateStyle
--snip--
# 根据人口数量将所有的国家分成三组
cc_pops_1, cc_pops_2, cc_pops_3 = {}, {}, {}
for cc, pop in cc_populations.items():
--snip--
wm_style = RotateStyle('#336699', base_style=LightColorizedStyle)
--snip--
这时打开最后的svg就可以看到世界地图中人口分布情况了,鼠标移动到指定国家会显示他的人口数据