谈谈Python实战数据可视化之pygal模块(实战篇)

前沿

通过上一节谈谈Python实战数据可视化之pygal模块(基础篇)的学习,我们对pygal模块的使用有了初步的了解,本节将以实战项目来加深pygal模块的使用。从网上可以下载JSON格式的人口数据,并使用json模块来处理它们,pygal模块提供了一个适合初学者使用的地图创建工具,我们将使用它来对人口数据进行可视化,以探索全球人口的分布情况。针对JSON格式的人口数据文件,可以通过谈谈Python实战数据可视化之matplotlib模块(实战篇)章节的配套资源来下载。对于本人在学习和编码过程种遇到的问题,我都会逐一解决。

小插曲之执行效率

我在学习过程中,走各方论坛,发现一个有趣的帖子。是针对Python执行效率问题的探究------加一行代码让python的运行速度提高100倍。什么代码这么强大?我们测试看看,从1一直累加到1亿。
(1)原始代码:

import time

def foo(x, y):
    tt = time.time()  # time.time()函数返回当前时间的时间戳(1970 纪元年后经过的浮点秒数)
    s = 0
    for i in range(x, y):
        s += i
    print(‘Time used: {} sec‘.format(time.time() - tt))
    return s

print(foo(1, 100000000))

什么是时间戳?时间戳表示的是从 1970 年 1 月 1 日 00:00:00 开始按秒计算的偏移量(time.gmtime(0))此模块中的函数无法处理 1970 纪元年以前的日期和时间或太遥远的未来(处理极限取决于 C 函数库,对于 32 位系统来说,是 2038 年)。
运行结果如下:

(2)加一行代码,再看看结果:

from numba import jit  # 添加的代码
import time

@jit  # 添加的代码
def foo(x, y):
    tt = time.time()  # time.time()函数返回当前时间的时间戳(1970 纪元年后经过的浮点秒数)
    s = 0
    for i in range(x, y):
        s += i
    print(‘Time used: {} sec‘.format(time.time() - tt))
    return s

print(foo(1, 100000000))

运行结果如下:

总结:原始代码测试出来的是23sec,加了一行代码就编程0.25sec了,好像真的变快了将近100倍耶。具体实现原理貌似有点复杂,等以后知识面广了再研究内部原理吧。

JSON格式数据

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写。例如:

[
  {
    "Country Name": "Arab World",
    "Country Code": "ARB",
    "Year": "1960",
    "Value": "96388069"
  },
  {
    "Country Name": "Arab World",
    "Country Code": "ARB",
    "Year": "1961",
    "Value": "98882541.4"
  },
....
....
....

可以看出,这个文件实际上就是一个很长的Python列表,其中每个元素都是一个包含四个键的字典:国家名、国别码、年份以及表示人口数量的值。

提取JSON格式文件的数据

在工程目录下,创建一个world_population.py文件,并将population_data.json格式文件放到工程目录下。然后编写以下代码尝试提取经json模块转化后的格式数据:

# 导入json模块分析JSON格式文件
import json

filename = ‘population_data.json‘
with open(filename) as f:
    # 函数json.load()将数据(文件对象)转换为Python能处理的格式,
    pop_data = json.load(f)  # pop_data是一个列表,每个元素都包含一个四个键的字典

for pop_dict in pop_data:
    # 只刷选出2010年份的国家人口数量
    if pop_dict[‘Year‘] == ‘2010‘:
        # 将每个国家的国家名、国家人口数保存并打印输出
        country_name = pop_dict[‘Country Name‘]
        population = int(float(pop_dict[‘Value‘]))
        print(country_name + ":" + str(population))

运行结果如下:

需要注意的是,上面代码获取pop_dict[‘Value‘]的值是一个字符串,而后面我们进行数据可视化时,人口数量必须使用数值才行,所以,我们先转化为float类型,再转化为int类型。为什么不直接转化为Int类型?这是因为当for循环遍历到人口数值是包含小数点的字符串(例如:‘1127437398.85751‘)时,Python不能直接转化为整数,不然会出现类似下面的报错:

为了消除这种错误,正确的做法是先将‘1127437398.85751‘字符串转化为float类型(1127437398.85751),再转化为Int类型(1127437398)。

获取两个字母的国别码

Pygal中的地图制作工具要求数据为特定的格式:用国别码表示国家,以及用数字表示人口数量。最重要的问题是,population_data.json中包含的是三个字母的国别码,但Pygal使用两个字母的国别码(存储在i18n模块中,其实是在该模块的一个字典COUNTRIES里,该字典包含的键和值分别为两个字母的国别码和国家名)来表示国家。所以我们要解决的问题就是根据国家名在i18n模块中的字典COUNTRIES里获取两个字母的国别码。这样就可以在世界地图上表示的国别码和人口数量分别使用字典COUNTRIES里的两个字母的国别码和population_data.json文件里的人口数量。好了,说了解决问题的流程,现在我们尝试使用i18n模块来获取字典COUNTRIES里的键和值,先在工程目录下创建一个country_codes.py文件。
需要注意的是书本P327页的16.2.4小节,导入i18n模块的方法对于现在来说已经不适用了。如果导入模块的代码写“from pygal.i18n import COUNTRIES”就会报以下的错误:

应该改为“from pygal_maps_world.i18n import COUNTRIES”才行。
代码如下:

# 返回il8n模块中COUNTRIES字典中对应国家名的国别码
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  # 如果没有找到则返回None

修改world_population.py文件的代码,代码如下:

# 导入json模块分析JSON格式文件
import json
from country_codes import get_country_code

filename = ‘population_data.json‘
with open(filename) as f:
    # 函数json.load()将数据(文件对象)转换为Python能处理的格式,
    pop_data = json.load(f)  # pop_data是一个列表,每个元素都包含一个四个键的字典

for pop_dict in pop_data:
    # 只刷选出2010年份的国家人口数量
    if pop_dict[‘Year‘] == ‘2010‘:
        # 将每个国家的国家名、国家人口数保存并打印输出
        country_name = pop_dict[‘Country Name‘]
        population = int(float(pop_dict[‘Value‘]))
        code = get_country_code(country_name)  # 将population_data.json文件获取的国家名传入函数,若存在则返回对应的国别码
        if code:  # 如果存在则输出国家名对应的国别码
            print(code + ":" + str(population))
        else:
            print(‘ERROR - ‘+country_name)

运行结果如下:

从上图可以看出,其实有相当一部分国家没有对应的国别码,导致显示错误消息的原因有两个。第一,并非所有人口数量都是国家,有些是地区和经济类群。第二,有些统计数据使用了不同的完整国家名,所以识别不到。

制作世界地图

有了两个字母的国别码后,我们可以进行以下步骤:
1.构造虚拟数据制作一个世界地图显示指定了国别码的国家有哪些,还有呈现人口数量,来感受一下世界地图的宏伟。
2.绘制一个2010年真实数据的完整的世界人口地图图表。
3.根据人口数量将国家分组
4.世界人口地图图表进行样式优化处理。
(1)制作一个模拟数据世界地图
在此之前,P329页16.2.5小节的代码中调用函数创建世界地图的方法对于现在也不适用了,如果代码写“wm = pygal.Worldmap() ”会报以下错误

将代码改为“wm = pygal.maps.world.World()”就可以通过了。代码如下:

import pygal

wm = pygal.maps.world.World()  # 创建一个实例
wm.title = ‘North,Central America‘

# 利用add函数添加标签和国家名还有人口数量,若参数2是一个列表(只有国家名,没有指定人口数量),默认指定人口数量为1,那么就是使用同一种颜色,并且颜色深浅一样,除非人口数量不同。
# 而参数2如果是一个字典,那么说明指定国家名的同时还指定了人口数量,那么虽然使用同一种类型颜色,但根据人口数量的多少决定颜色的深浅
wm.add(‘North America‘, {‘ca‘: 10000, ‘mx‘: 20000, ‘us‘: 30000})
wm.add(‘Central America‘, {‘bz‘: 40000, ‘cr‘: 50000, ‘gt‘: 60000, ‘hn‘: 70000, ‘ni‘: 80000, ‘pa‘: 90000, ‘sv‘: 100000})

wm.render_to_file(‘americas.svg‘)

将americas.svg放入浏览器中显示,运行结果如下:

上面的人口数据纯属虚构。从上图可以看出,将鼠标移至国家上方便可显示国家名和人口数,North America的三个国家分别使用同一种、但深浅不一的颜色来表示,其中人口数量越大,颜色越深。而Central America的多个国家也是同样如此。
(2)绘制完整的世界人口地图
要呈现其他国家的人口数量,需要将前面处理的数据(两个字母的国别码和对应国家的人口数量)转换为Pygal要求的字典格式(即作为实参传入add函数的第二个形参)。代码如下:

import json
import pygal
from country_codes import get_country_code

filename = ‘population_data.json‘
with open(filename) as f:
    # 函数json.load()将数据(文件对象)转换为Python能处理的格式,
    pop_data = json.load(f)  # pop_data是一个列表,每个元素都包含一个四个键的字典

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‘)

运行结果如下:

根据上面可以总结出:若将整个世界所有国家的国别码和人口数量都放进一个字典里,再调用一个add函数添加进世界地图,那么就会把这个字典当成一个组,那么在世界地图显示时,使用同一种、但深浅不一的红颜色来表示,其中人口数量越大,颜色越深。再想想,这可不太行,因为整体来看,很难反映其人口数量的差别,为了解决这个问题,我们究其根源,主要是我们只使用了一个字典和只调用了一个add函数来表示整个世界的原因导致颜色单一,解决办法是我们可以对其进行分组处理,人口数量多的为一组,人口数量中等的为一组,人口数量少的为一组,那么就分为三组了。

根据人口数量将国家分组

针对上一节结论的分析,我们这一小节将采用分组的方式反映人口数量的差别。根据人口数量分成三组:少于1000万的、介于1000万和10亿之间的以及超过10亿的。
代码如下:

import json
import pygal
from country_codes import get_country_code

filename = ‘population_data.json‘
with open(filename) as f:
    # 函数json.load()将数据(文件对象)转换为Python能处理的格式,
    pop_data = json.load(f)  # pop_data是一个列表,每个元素都包含一个四个键的字典

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 < 1000000000:
        cc_pops_2[cc] = pop
    else:
        cc_pops_3[cc] = pop

wm = pygal.maps.world.World()  # 创建一个实例
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‘)

运行结果如下:

从上图可以看出,世界地图使用三种不同的颜色,更直观地看出人口数量的差别,在每组中,各个国家都按人口从少到多以浅到深的颜色。其中中国和印度是大于10亿人的国家。

世界人口地图图表进行样式优化处理

前面的案例,采用默认的颜色设置不怎么好看,我们可以使用Pygal样式设置指令来调整颜色。Pygal样式存储在模块style中,我们从这个模块中导入了RotateStyle类,创建这个类的实例时,需要提供一个实参 —— 十六进制的 RGB 颜色。十六进制格式 的 RGB 颜色是一个以井号( # )打头的字符串,后面跟着 6 个字符,其中前两个字符表示红色分量,接下来的两个表示绿色分量,最后两个表示蓝色分量。每个分量的取值范围为 00 (没有相应的颜色) ~FF (包含最多的相应颜色)。Pygal 通常默认使用较暗的颜色主题。使用 LightColorizedStyle 加亮了地图的颜色。
代码如下:

import json
import pygal
from country_codes import get_country_code
from pygal.style import LightColorizedStyle as LCS,RotateStyle as RS  # 导入RotateStyle和 LightColorizedStyle,并取了别名,后面调用就采用别名,方便多了

filename = ‘population_data.json‘
with open(filename) as f:
    # 函数json.load()将数据(文件对象)转换为Python能处理的格式,
    pop_data = json.load(f)  # pop_data是一个列表,每个元素都包含一个四个键的字典

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 < 1000000000:
        cc_pops_2[cc] = pop
    else:
        cc_pops_3[cc] = pop

wm_style = RS(‘#336699‘,base_style=LCS)  # 一个样式对象,参数指定一个十六进制的RGB颜色
wm = pygal.maps.world.World(style=wm_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‘)

运行结果如下:

原文地址:http://blog.51cto.com/12731497/2160650

时间: 2024-11-23 21:56:50

谈谈Python实战数据可视化之pygal模块(实战篇)的相关文章

谈谈Python实战数据可视化之pygal模块(基础篇)

前沿 对于需要在尺寸不同的屏幕上显示的图表,请考虑使用Pygal来生成它们,因为它们将自动缩放,以适合观看者的屏幕,这样它们在任何设备上显示时都会很美观.接下来我会谈谈pygal模块生成线.直方图的基本用法,用书本骰子的案例来更深入了解pygal模块的使用,对于pygal其他图形的创建其实方法差不多,实际运用时需要制作哪种图形就去官网查询,官网有很多图形创建的示例代码,pygal画廊官网链接:http://www.pygal.org/如下方图(有图有代码,自己打一遍其实懂得也差不多了): pyg

谈谈Python实战数据可视化之pyplot模块

前沿 Python提供了很多模块用于数据可视化,其中有matplotlib.pygal.我参考网上热门书籍<Python编程从入门到实战>,在测试与学习过程中遇到的些许问题加以解决,才写下这一项目实战的心得,对于Python基础部分就不细讲,主要是项目核心要点和解决方案的描述.本小节先讲述pyplot模块的基本使用. 新手的建议 针对新手,真心觉得不要直接使用Python下载来的IDLE来开发,因为功能太少了,也不好使用.我的建议是对于Python初学者,先安装Anaconda,这是一个基于P

百度数据可视化图表套件echart实战

最近我一直在做数据可视化的前端工作,我用的最多的绘图工具是d3.d3有点像photoshop,功能很强大,例子也很多,但是学习成本也不低,做项目是需要较大人力投入的.3月底由在亚马逊工作的同学介绍下使用了一下echart,一个由百度前端发起的canvas国产类库(官网:http://echarts.baidu.com/index.html).这个echart其实是在canvas类库zrender的基础上做的主题图库,优点有数据驱动,图例丰富,功能强大,支持数据拖拽重计算,数据区域漫游,全中文文档

Python数据可视化(Pygal、svg、csv、Bar、Line)

一.pygal(图表类型Bar) 将使用Python可视化包Pygal来生成可缩放的矢量图形文件 pygal官方文档:[www.pygal.org/en/stable/](http://www.pygal.org/en/stable/) 1.安装pygal pip install pygal -i https://pypi.tuna.tsinghua.edu.cn/simple 2.简单的python图表 import pygal pygal.Bar()(1, 3, 3, 7)(1, 6, 6,

Python - matplotlib 数据可视化

在许多实际问题中,经常要对给出的数据进行可视化,便于观察. 今天专门针对Python中的数据可视化模块--matplotlib这块内容系统的整理,方便查找使用. 本文来自于对<利用python进行数据分析>以及网上一些博客的总结. 1  matplotlib简介 matplotlib是Pythom可视化程序库的泰斗,经过几十年它仍然是Python使用者最常用的画图库.有许多别的程序库都是建立在它的基础上或直接调用它,比如pandas和seaborn就是matplotlib的外包, 它们让你使用

基于Python的数据可视化库pyecharts介绍

什么是pyecharts? pyecharts 是一个用于生成 Echarts 图表的类库. echarts 是百度开源的一个数据可视化 JS 库,主要用于数据可视化.pyecharts 是一个用于生成 Echarts 图表的类库.实际上就是 Echarts 与 Python 的对接. 使用 pyecharts 可以生成独立的网页,也可以在 flask , Django 中集成使用.pyecharts包含的图表 Bar .Bar3D.Boxplot.EffectScatter .Funnel.G

Python图表数据可视化Seaborn:3. 线性关系| 时间线| 热图

1. 线性关系数据可视化 lmplot() import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns % matplotlib inline sns.set_style("darkgrid") sns.set_context("paper") # 设置风格.尺度 import warnings warnings.filterwarnings

Python图表数据可视化Seaborn:2. 分类数据可视化

1. 分类数据可视化 - 分类散点图 stripplot() / swarmplot() import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns % matplotlib inline sns.set_style("whitegrid") sns.set_context("paper") # 设置风格.尺度 import warnings

Python进行数据可视化的9种常见方法,总有一种是你要用的

其实利用 Python 可视化数据并不是很麻烦,因为 Python 中有两个专用于可视化的库 matplotlib 和 seaborn 能让我们很容易的完成任务. 我们用 Python 可以做出哪些可视化图形? 当你给别人一个表格比如: 这个表给别人看起来,既不舒服,也不好观看.最最最最最最重要的一点就是low! 在学习过程中有什么不懂得可以加我的 python学习交流扣扣qun,784758214 群里有不错的学习视频教程.开发工具与电子书籍. 与你分享python企业当下人才需求及怎么从零基