Python学习之路日志—利用matplotlib开发数据可视化项目(5)

在今晚,我将学习新的内容,我会下载JSON格式的人口数据,并使用json 模块来处理它们。

4.2 制作世界人口地图:

4.2.1 下载与提取世界人口数据:

将文件population_data.json复制到本章程序所在的文件夹中,这个文件包含全球大部分国家1960~2010年的人口数据。我们来研究一下population_data.json,看看如何着手处理这个文件中的数据:

在这里插入图片描述

这个文件实际上就是一个很长的Python列表,其中每个元素都是一个包含四个键的字典:国家名、国别码、年份以及表示人口数量的值。我们只关心每个国家2010年的人口数量, 因此我们首先编写一个打印这些信息的程序:

在这里插入图片描述

import json

# Load data into a list
filename = 'population_data.json'
with open(filename) as f:
	pop_data = json.load(f)

# Print the population of each country in 2010
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)

我们首先导入了模块json ,以便能够正确地加载文件中的数据,然后,我们将数据存储在pop_data 中(见第6行)。函数json.load() 将数据转换为Python能够处理的格式, 这里是一个列表。在第9行处,我们遍历pop_data 中的每个元素。每个元素都是一个字典,包含四个键—值对,我们将每个字典依次存储在pop_dict 中。 在第10行处,我们检查字典的'Year' 键对应的值是否是2010(由于population_data.json中的值都是用引号括起的,因此我们执行的是字符串比较)。如果年份为2010,我们就将与'Country Name' 相关联的值存储到country_name 中,并将与'Value' 相关联的值存储在population 中(见第12行)。接下来,我们打印每个国家的名称和人口数量。

但我在这里遇到了一个问题,在我执行程序后出现了这样的情况:

在这里插入图片描述
可以看到,出现了No JSON object could be decoded这样的提示。在我上网搜索后找到的解决办法是将json文件打开并以UTF8无BOM格式保存

在这里插入图片描述
解决问题后,可以看到输出为一系列国家的名称和人口数量:

在这里插入图片描述

4.2.2 将字符串转换为数字值:

population_data.json中的每个键和值都是字符串。为处理这些人口数据,我们需要将表示人口数量的字符串转换为数字值,为此我们使用函数int()

在这里插入图片描述

import json

# Load data into a list
filename = 'population_data.json'
with open(filename) as f:
	pop_data = json.load(f)

# Print the population of each country in 2010
for pop_dict in pop_data:
	if pop_dict['Year'] == '2010':
		country_name = pop_dict['Country Name']
		population = int(pop_dict['Value'])
		print(country_name + ':' + str(population))

在第12行处,我们将每个人口数量值都存储为数字格式。打印人口数量值时,需要将其转换为字符串(见第13行)。 然而,如上图所示,对于有些值,这种转换会导致错误。

原始数据的格式常常不统一,因此经常会出现错误。导致上述错误的原因是,Python不能直接将包含小数点的字符串’1127437398.85751’ 转换为整数(这个小数值可能是人口数据缺失时通过插值得到的)。为消除这种错误,我们先将字符串转换为浮点数,再将浮点数转换为整数:

在这里插入图片描述

import json

# Load data into a list
filename = 'population_data.json'
with open(filename) as f:
	pop_data = json.load(f)

# Print the population of each country in 2010
for pop_dict in pop_data:
	if pop_dict['Year'] == '2010':
		country_name = pop_dict['Country Name']
		population = int(float(pop_dict['Value']))
		print(country_name + ':' + str(population))

函数float() 将字符串转换为小数,而函数int() 丢弃小数部分,返回一个整数。现在,我们可以打印2010年的完整人口数据,不会导致错误了:

在这里插入图片描述
每个字符串都成功地转换成了浮点数,再转换为整数。

4.2.3 获取两个字母的国别码:

制作地图前,还需要解决数据存在的最后一个问题。Pygal中的地图制作工具要求数据为特定的格式:用国别码表示国家,以及用数字表示人口数量。处理地理政治数据时,经常需要用到几个标准化国别码集。

population_data.json中包含的是三个字母的国别码,但Pygal使用两个字母的国别码。我们需要想办法根据国家名获取两个字母的国别码。 Pygal使用的国别码存储在模块i18n (internationalization的缩写)中。字典COUNTRIES 包含的键和值分别为两个字母的国别码和国家名。要查看这些国别码,可从模块i18n 中导入这个字典,并打印其键和值:

在这里插入图片描述

但出错了,我上网搜索后发现,pygal.i18n 已经不存在了,现在已经更改成了 pygal_maps_world ,需要单独通过pip3下载:

在这里插入图片描述
安装成功之后,将第1行代码改成如下所示,就可以正常调用国别码了:

在这里插入图片描述

from pygal_maps_world.i18n import COUNTRIES

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

在上面的for 循环中,我们让Python将键按字母顺序排序(见第3行),然后打印每个国别码及其对应的国家。为获取国别码,我们将编写一个函数,它在COUNTRIES 中查找并返回国别码。我们将这个函数放在一个名为country_codes 的模块中,以便能够在可视化程序中导入它:

在这里插入图片描述

# -*- coding:utf-8 -*-

from pygal_maps_world.i18n import COUNTRIES

def get_country_code(country_name):
	"""根据指定的国家,返回Pygal使用的两个字母的国别码"""
	for code, name in COUNTRIES.items():
		if name == country_name:
			return code

	# 如果没有找到指定的国家,就返回None
	return None

print(get_country_code('United Arab Emirates'))
print(get_country_code('Andorra'))
print(get_country_code('Afghanistan'))

get_country_code() 接受国家名,并将其存储在形参country_name 中(见第5行)。接下来,我们遍历COUNTRIES 中的国家名—国别码对(见第7行);如果找到指定的国家名,就返回相应的国别码(见第8-9行)。在循环后面,我们在没有找到指定的国家名时返回None (见第12行)。最后,我们使用了三个国家名来调用这个函数,以核实它能否正确地工作。与预期的一样,这个程序输出了三个由两个字母组成的国别码。

接下来,在world_population.py中导入get_country_code:

在这里插入图片描述

import json

from country_codes import get_country_code

# Load data into a list
filename = 'population_data.json'
with open(filename) as f:
	pop_data = json.load(f)

# Print the population of each country in 2010a
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(country_name + ':' + str(population))

有了国别码后,制作世界地图易如反掌。Pygal提供了图表类型Worldmap ,可帮助你制作呈现各国数据的世界地图。为演示如何使用Worldmap ,我们来创建一个突出北美、中美和南美的简单地图:

4.2.4 制作世界地图:

在这里插入图片描述
在第3行处,我们创建了一个Worldmap 实例,并设置了该地图的title 属性。在第6-8行处,我们使用了方法add() ,它接受一个标签和一个列表,其中后者包含我们要突出的国家 的国别码。每次调用add() 都将为指定的国家选择一种新颜色,并在图表左边显示该颜色和指定的标签。我们要以同一种颜色显示整个北美地区,因此第一次调用add() 时, 在传递给它的列表中包含'ca''mx''us' ,以同时突出加拿大、墨西哥和美国。接下来,对中美和南美国家做同样的处理。

但是却出现了错误,在一番搜索后,我发现可将代码的前两行改成如下所示:

在这里插入图片描述

import pygal_maps_world.maps

wm = pygal_maps_world.maps.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')

第13行处的方法render_to_file() 创建一个包含该图表的.svg文件,可以在浏览器中打开它。输出是一幅以不同颜色突出北美、中美和南美的地图,如下图所示:

在这里插入图片描述


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值