世界人口地图绘制(Python)

1.下载并处理数据

制作地图需要 JSON 文件。JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。《python编程从入门到实践》中给出的网址已经更改为https://datahub.io/,进入网站后在搜索框中输入population

然后找到population total这个选项,左击进入后选择json文件,点击进入后另存为data.json即可。

PS:http://www.ourd3js.com/wordpress/668/这个网站上也有丰富的json格式的人口数据可以下载。

下载好json数据后进行处理

import json

if __name__ == '__main__':
    #打开data.json文件
    filename = 'data.json'
    with open(filename) as f:
        pop_data = json.load(f)
    #查看json文件的数据,不难发现是一个很长的json列表,每一元素为包含4个键的字典:国别码、国家名、年份以及人口数。
    #我们取年份为2016,注意该文件中的年份为int型,原书自带的文件中年份为字符型。
    for pop_dict in pop_data:
        if pop_dict['Year'] == 2016:
            country_name = pop_dict['Country Name']
            #由于存在小数,所以用int取整
            population = int(pop_dict['Value'])
            print(country_name + ':' + str(population))

运行结果如下:

考虑到Pygal的地图制作工具要求数据为特定的格式:用两位字母的国别码表示国家,而本json文件为三位字母的国别码,所以需要进一步处理。创建获取两位国别码的函数get_country_code。

注意:原书中import pygal.i18n,目前pygal中已经不包含这个模块。所以需要安装pygal_maps_world(pip安装即可,不详说)

from pygal_maps_world.i18n import COUNTRIES

def get_country_code(country_name):
    #在COUNTRIES中查找并返回国别码
    for code, name in COUNTRIES.items():
        if name == country_name:
            return code
    return None

修改主函数,将原先输出的国家名改为国别码,同时将人口分为3类,小于1亿,小于10亿,和超过10亿

if __name__ == '__main__':
    #打开data.json文件
    filename = 'data.json'
    with open(filename) as f:
        pop_data = json.load(f)
    #查看json文件的数据,不难发现是一个很长的json列表,每一元素为包含4个键的字典:国别码、国家名、年份以及人口数。
    #cc_pop1,cc_pop2,cc_pop3分别存放小于1亿,小于10亿,超过10亿的数据
    cc_pop1, cc_pop2, cc_pop3 = {},{},{}
    for pop_dict in pop_data:
        #我们取年份为2016,注意该文件中的年份为int型,原书自带的文件中年份为字符型。
        if pop_dict['Year'] == 2016:
            country_name = pop_dict['Country Name']
            #获取国别码
            country_code = get_country_code(country_name)
            if country_code:
                #由于存在小数,所以用int取整
                population = int(pop_dict['Value'])
                print(country_code + ':' + str(population))
                #进行分类
                if population < 100000000:
                    cc_pop1[country_code] = population
                elif population < 1000000000:
                    cc_pop2[country_code] = population
                else:
                    cc_pop3[country_code] = population
            else:
                print("Error: " + country_name)

运行结果如下:

目前为止,数据处理完毕,可以正式开始绘制地图。

2.绘制地图并优化

创建绘制地图的函数draw_map。

注意:原书用的pygal.worldmap(),目前也不存在,改用pygal.maps.world.World()

import pygal

def draw_map(pcc_pop1, cc_pop2, cc_pop3):
    #绘制地图
    wn = pygal.maps.world.World()
    #添加标题
    wn.title = '2016世界人口地图'
    #add()将一系列值添加到图表中
    wn.add('0-1亿',cc_pop1)
    wn.add('1亿-10亿',cc_pop2)
    wn.add('超过10亿',cc_pop3)
    #渲染为SVG文件,直接用浏览器打开即可
    wn.render_to_file('world_population.svg')

主函数中添加一句:

draw_map(cc_pop1, cc_pop2, cc_pop3)

运行结果:

地图基本成型,现在进一步优化一下,主要改一改样式

from pygal.style import RotateStyle
from pygal.style import LightColorizedStyle
#使用#336699的颜色,让地图呈现淡蓝色基色
#使用LightColorizedStyle加量地图主题
wn = pygal.maps.world.World(style = RotateStyle('#336699',base_style=LightColorizedStyle))

最终运行结果:

总程序:

import json
from pygal_maps_world.i18n import COUNTRIES
import pygal.maps
from pygal.style import RotateStyle
from pygal.style import LightColorizedStyle

def get_country_code(country_name):
    #在COUNTRIES中查找并返回国别码
    for code, name in COUNTRIES.items():
        if name == country_name:
            return code
    return None
def draw_map(pcc_pop1, cc_pop2, cc_pop3):
    #绘制地图
    #使用#336699的颜色,让地图呈现淡蓝色基色
    #使用LightColorizedStyle加量地图主题
    wn = pygal.maps.world.World(style = RotateStyle('#336699',base_style=LightColorizedStyle))
    #添加标题
    wn.title = '2016世界人口地图'
    #add()将一系列值添加到图表中
    wn.add('0-1亿',cc_pop1)
    wn.add('1亿-10亿',cc_pop2)
    wn.add('超过10亿',cc_pop3)
    #渲染为SVG文件,直接用浏览器打开即可
    wn.render_to_file('world_population.svg')

if __name__ == '__main__':
    #打开data.json文件
    filename = 'data.json'
    with open(filename) as f:
        pop_data = json.load(f)
    #查看json文件的数据,不难发现是一个很长的json列表,每一元素为包含4个键的字典:国别码、国家名、年份以及人口数。
    #cc_pop1,cc_pop2,cc_pop3分别存放小于1亿,小于10亿,超过10亿的数据
    cc_pop1, cc_pop2, cc_pop3 = {},{},{}
    for pop_dict in pop_data:
        #我们取年份为2016,注意该文件中的年份为int型,原书自带的文件中年份为字符型。
        if pop_dict['Year'] == 2016:
            country_name = pop_dict['Country Name']
            #获取国别码
            country_code = get_country_code(country_name)
            if country_code:
                #由于存在小数,所以用int取整
                population = int(pop_dict['Value'])
                print(country_code + ':' + str(population))
                #进行分类
                if population < 100000000:
                    cc_pop1[country_code] = population
                elif population < 1000000000:
                    cc_pop2[country_code] = population
                else:
                    cc_pop3[country_code] = population
            else:
                print("Error: " + country_name)
    draw_map(cc_pop1, cc_pop2, cc_pop3)

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值