第十章、数据可视化 - 折线图可视化
效果:2020年印美日新冠累计确诊人数
2020年是新冠疫情爆发的一年,随着疫情的爆发,国内外确诊人数成了大家关心的热点,相信大家都有看过类似的疫情报告.本案例对印度美国日本三个国家确诊人数的进行了可视化处理,形成了可视化的疫情确诊人数报告.
数据来源
本案例数据全部来自>,及公开的全球各国GDP数据
使用的技术
Echarts 是个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可.而Python是门富有表达力的语言,很适合用于数据处理.当数据分析遇上数据可视化时pyecharts诞生了.
json数据格式
什么是json
JSON是一种轻量级的数据交互格式。可以按照JSON指定的格式去组织和封装数据
JSON本质上是一个带有特定格式的字符串
主要功能:json就是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互.类似于:
- 国际通用语言 - 英语
- 中国56个民族不同地区的通用语言 - 普通话
json有什么用
各种编程语言存储数据的容器不尽相同,在Python中有字典dict这样的数据类型,而其它语言可能没有对应的字典
为了让不同的语言都能够相互通用的互相传递数据,JSON就是一种非常良好的中转数据格式。如下图,以Python和C语言互传数据为例:
Python格式数据 → Json格式数据 → C语言程序接受Json格式数据并转化为C格式数据继续使用
C格式数据 → Json格式数据 → Python语言程序接受Json格式数据并转化为Pvthon格式数据继续使用
json格式数据转化
json格式的数据要求很严格, 下面我们看一下他的要求
# json数据的格式可以是:
{"name":"admin”,"age":18}
# 也可以是:
[{"name":"admin","age":18},{"name":"root","age":16},{"name":"张三”,"age":20}]
Python数据和Json数据的相互转化
import json
# 准备列表,列表内每一个元素都是字典,将其转换为JSON
data = [{"name": "张大山", "age": 11} , {"name": "王大锤", "age": 13}, {"name": "赵小虎", "age": 16}]
json_str = json.dumps(data, ensure_ascii=False)
print(type(json_str))
print(json_str)
# 准备字典,将字典转换为JSON
d = {"name":"周杰伦", "addr":"台北"}
json_str = json.dumps(d, ensure_ascii=False)
print(type(json_str))
print(json_str)
# 将JSON字符串转换为Python数据类型[{k: v, k: v}, {k: v, k: v}]
s = '[{"name": "张大山", "age": 11} , {"name": "王大锤", "age": 13}, {"name": "赵小虎", "age": 16}]'
l = json.loads(s)
print(type(l))
print(l)
# 将JSON字符串转换为Python数据类型{k: v, k: v}
s = '{"name":"周杰伦", "addr":"台北"}'
d = json.loads(s)
print(type(d))
print(d)
总结
1.json:是一种轻量级的数据交互格式,采用完全独立于编程语言的文本格式来存储和表示数据(就是字符串)
Python语言使用JSON有很大优势,因为:JSON无非就是一个单独的字典或一个内部元素都是字典的列表
所以SON可以直接和Python的字典或列表进行无缝转换。
2.json格式数据转化
通过 json.dumps(data)方法把python数据转化为了json数据
data = json.dumps(data)
如果有中文可以带上:ensure_ascii=False参数来确保中文正常转换
通过json. loads (data)方法把josn数据转化为了python列表或字典
data = json. loads(data)
pyecharts模块介绍
pyecharts模块
如果想要做出数据可视化效果图,可以借助pyecharts模块来完成
概况:
Echarts是个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可.而Python是门富有表达力的语言,很适合用于数据处理.当数据分析遇上数据可视化时pyecharts诞生了.
pyecharts模块安装
使用在前面学过的pip命令即可快速安装PyEcharts模块
pip install pyecharts
总结
1.开发可视化图表使用的技术栈是:
Echarts框架的Python版本:PyEcharts包
2.如何安装PyEcharts包:
pip install pyecharts
3.如何查看官方示例
打开官方画廊:
https://gallery.pyecharts.org/#/README
pyecharts快速入门
pyechars入门
基础折线图:
# 导包,导入Line功能构建折线图对象
from pyecharts.charts import Line
# 得到折线图对象
line = Line()
# 添加x轴数据
line.add_xaxis(["中国", "美国", "英国"])
# 添加y轴数据
line.add_yaxis("GDP", [30, 20, 10])
# 生成图表
line.render()
pyecharts有哪些配置选项
pyecharts模块中有很多的配置选项, 常用到2个类别的选项:
- 全局配置选项
- 系列配置选项
set_global_opts方法
这里全局配置选项可以通过set_global_opts方法来进行配置,相应的选项和选项的功能如下:
TitleOpts:标题配置项
LegendOpts:图例配置项
ToolboxOpts:工具箱配置项
TooltipOpts:提示框配置项
VisualMapOpts:视觉映射配置项
DataZoomOpts:区域缩放配置项
line.set_global_opts(
title_opts=opts.TitleOpts(title="测试", pos_left="center", pos_bottom="1%"),
legend_opts=opts.LegendOpts(is_show=True),
toolbox_opts=opts.ToolboxOpts(is_show=True),
visualmap_opts=opts.VisualMapOpts(is_show=True),
tooltip_opts=opts.TooltipOpts(is_show=True),
)
总结
1.pyecharts模块中有很多的配置选项,常用到三个类别的选项:
全局配置选项
系列配置选项
2.全局配置项能做什么?
- 配置图表的标题
- 配置图例
- 配置鼠标移动效果
- 配置工具栏
- 等整体配置项
创建折线图
import json
from pyecharts.charts import Line
from pyecharts.options import TitleOpts, LabelOpts # 处理数据
f_us = open("D:/美国.txt", "r", encoding="UTF-8")
us_data = f_us.read() # 美国的全部内容
f_jp = open("D:/日本.txt", "r", encoding="UTF-8")
jp_data = f_jp.read() # 日本的全部内容
f_in = open("D:/印度.txt", "r", encoding="UTF-8")
in_data = f_in.read() # 印度的全部内容
# 去掉不合JSON规范的开头
us_data = us_data.replace("jsonp_1629344292311_69436(", "")
jp_data = jp_data.replace("jsonp_1629350871167_29498(", " ")
in_data = in_data.replace("jsonp_1629350745930_63180(", "")
# 去掉不合JSON规范的结尾
us_data = us_data[:-2]
jp_data = jp_data[:-2]
in_data = in_data[:-2]
# JSON转Python字典
us_dict = json.loads(us_data)
jp_dict = json.loads(jp_data)
in_dict = json.loads(in_data)
# 获取trend key
us_trend_data = us_dict['data'][0]['trend']
jp_trend_data = jp_dict['data'][0]['trend']
in_trend_data = in_dict['data'][0]['trend']
# 获取日期数据,用于x轴,取2029年(到314下标结束)
us_x_data = us_trend_data['updateDate'][:314]
jp_x_data = jp_trend_data['updateDate'][:314]
in_x_data = in_trend_data['updateDate'][:314]
# 获取确认数据, 用于y轴,取2020年(到314下标结束)
us_y_data = us_trend_data['list'][0]['data'][:314]
jp_y_data = jp_trend_data['list'][0]['data'][:314]
in_y_data = in_trend_data['list'][0]['data'][:314]
# 生成图表
line = Line() # 构建折线图对象
# 添加x轴数据
line.add_xaxis(us_x_data) # x轴是共用的,所以使用一个国家的数据即可
# 添加y轴数据
line.add_yaxis("美国确诊人数", us_y_data, label_opts=LabelOpts(is_show=False)) # 添加美国的y轴数据
line.add_yaxis("日本确诊人数", jp_y_data, label_opts=LabelOpts(is_show=False)) # 添加日本的y轴数据
line.add_yaxis("印度确诊人数", in_y_data, label_opts=LabelOpts(is_show=False)) # 添加印度的y轴数据
# 设置全局选项
line.set_global_opts(
title_opts=TitleOpts(title="2020年美日印三国确诊人数对比折线图", pos_left="center", pos_bottom="1%")
)
# 调用render方法,生成图表
line.render()
# 关闭文件对象
f_us.close()
f_jp.close()
f_in.close()
第十一章,数据可视化 - 地图可视化
基础地图使用
基础地图演示
from pyecharts.charts import Map
# 准备地图对象
map = Map()
# 准备数据 data = [
("北京市", 99),
("上海市", 199),
("湖南省", 299),
("台湾省", 399),
("广东省", 499)
]
# 添加数据
map.add("测试地图", data, "china")
# 绘图
map.render()
基础地图演示-视觉映射器
# 设置全局选项
map.set_global_opts(
visualmap_opts=VisualMapOpts(
is_show=True,
is_piecewise=True,
pieces=[
{"min": 1, "max": 9, "label": "1-9人", "color": "#CCFFFF"},
{"min": 10, "max": 99, "label": "10-99人", "color": "#ff6666"},
{"min": 100, "max": 500, "label": "100-500人", "color": "#990033"}
]
)
)
# 绘图
map.render()
疫情地图-国内疫情地图
import json
from pyecharts.charts import Map
from pyecharts.options import *
# 读取数据文件
f = open("D:/疫情.txt", "r", encoding="UTF-8")
data = f.read() # 全部数据
# 关闭文件
f.close()
# 取到各省数据
# 将字符串json转换为python的字典
data_dict = json.loads(data) # 基础数据字典
# 从字典中取出省份的数据
province_data_list = data_dict["areaTree"][0]["children"]
# 组装每个省份和确诊人数为元组,并将各个省的数据都封装入列表内
data_list = [ ] # 绘图需要的元组列表
for province_data in province_data_list:
province_name = province_data["name"] # 省份名称
province_confirm = province_data["total"]["confirm"] # 确诊人数
data_list.append((province_name, province_confirm))
# 创建地图对象
map = Map()
# 添加数据
map.add("各省份确诊人数", data_list, "china")
# 设置全局配置,定制分段的视觉映射
map.set_global_opts(
title_opts=TitleOpts(title="全国疫情地图"),
visualmap_opts=VisualMapOpts(
is_show=True, # 是否显示
is_piecewise=True, # 是否分段
pieces=[
{"min": 1, "max": 99, "lable": "1~99人", "color": "#CCFFFF"},
{"min": 100, "max": 999, "lable": "100~999人", "color": "#FFFF99"},
{"min": 1000, "max": 4999, "lable": "1000~4999人", "color": "#FF9966"},
{"min": 5000, "max": 9999, "lable": "5000~9999人", "color": "#FF6666"},
{"min": 10000, "max": 99999, "lable": "10000~99999人", "color": "#CC3333"},
{"min": 100000, "lable": "100000+", "color": "#990033"},
]
)
)
# 绘图
map.render("全国疫情地图.html")
疫情地图-省级疫情地图
import json
from pyecharts.charts import Map
from pyecharts.options import *
# 读取文件
f = open("D:/疫情.txt", "r", encoding="UTF-8")
data = f.read()
# 关闭文件
f.close()
# 获取河南省数据
# 将json数据转换为python字典
data_dict = json.loads(data)
# 取到河南省数据
cities_data = data_dict["areaTree"][0]["children"][3]["children"]
# 准备数据为元组并放入list
data_list = [ ]
for city_data in cities_data:
city_name = city_data["name"] + "市"
city_confirm = city_data["total"]["confirm"]
data_list.append((city_name, city_confirm))
# 手动添加济源市的数据
data_list.append(("济源市", 5))
# 构建地图
map = Map()
map.add("河南省疫情发布", data_list, "河南")
# 设置全局选项
map.set_global_opts(
title_opts=TitleOpts(title="河南省疫情地图"),
visualmap_opts=VisualMapOpts(
is_show=True, # 是否显示
is_piecewise=True, # 是否分段
pieces=[
{"min": 1, "max": 99, "lable": "1~99人", "color": "#CCFFFF"},
{"min": 100, "max": 999, "lable": "100~999人", "color": "#FFFF99"},
{"min": 1000, "max": 4999, "lable": "1000~4999人", "color": "#FF9966"},
{"min": 5000, "max": 9999, "lable": "5000~9999人", "color": "#FF6666"},
{"min": 10000, "max": 99999, "lable": "10000~99999人", "color": "#CC3333"},
{"min": 100000, "lable": "100000+", "color": "#990033"},
]
)
)
# 绘图
map.render("河南省疫情地图.html")
第十二章,数据可视化 - 动态柱状图
案例效果
通过pyechars可以实现数据的动态显示,直观的感受1960~2019年全世界各国GDP的变化趋势
基础柱状图
通过Bar构建基础柱状图
from pyecharts.charts import Bar
from pyecharts.options import LabelOpts
# 使用Bar构建基础柱状图
bar = Bar()
# 添加x轴的数据
bar.add_xaxis(["中国", "美国", "英国"])
# 添加y轴的数据
bar.add_yaxis("GDP", [30, 20, 10], label_opts=LabelOpts(position="right"))
# 反转x轴和y轴
bar.reversal_axis()
# 绘图
bar.render("基础柱状图.html")
总结
1.通过Bar()构建一个柱状图对象
2.和折线图一样,通过add_xaxis()和add_yaxis()添加x和y轴数据
3.通过柱状图对象的:reversal_axis(),反转x和y轴
4.通过label_opts=LabelOpts(position="right")设置数值标签在右侧显示
基础时间线柱状图
创建时间线
Timeline()-时间线
柱状图描述的是分类数据,回答的是每一个分类中「有多少?」这个问题,这是柱状图的主要特点,同时柱状图很难动态的描述一个趋势性的数据。这里pyecharts为我们提供了一种解决方案-时间线
如果说一个Bar、Line对象是一张图表的话,时间线就是创建一个一维的x轴,轴上每一个点就是一个图表对象
from pyecharts.charts import Bar, Timeline
from pyecharts.options import LabelOpts
from pyecharts.globals import ThemeType
bar1 = Bar()
bar1.add_xaxis(["中国", "美国", "英国"])
bar1.add_yaxis("GDP", [30, 30, 20], label_opts=LabelOpts(position="right"))
bar1.reversal_axis()
bar2 = Bar()
bar2.add_xaxis(["中国", "美国", "英国"])
bar2.add_yaxis("GDP", [50, 50, 50], label_opts=LabelOpts(position="right"))
bar2.reversal_axis()
bar3 = Bar()
bar3.add_xaxis(["中国", "美国", "英国"])
bar3.add_yaxis("GDP", [70, 60, 60], label_opts=LabelOpts(position="right"))
bar3.reversal_axis()
# 构建时间线对象
timeline = Timeline({"theme": ThemeType.LIGHT})
# 在时间线内添加柱状图对象
timeline.add(bar1, "点1")
timeline.add(bar2, "点2")
timeline.add(bar3, "点3")
# 自动播放设置
timeline.add_schema(
play_interval=1000, # 自动播放的时间间隔,单位毫秒
is_timeline_show=True, # 是否在自动播放的时候显示时间线
is_auto_play=True, # 是否自动播放
is_loop_play=True # 是否循环自动播放
)
# 绘图是用时间线对象绘图,而不是bar对象了
timeline.render("基础时间线柱状图.html")
时间线设置主题
from pyecharts.globals import ThemeType
# 创建时间线对象
timeline = Timeline(
{"theme": ThemeType.LIGHT}
)
编号 颜色 备注
ThemeType.WHITE 红蓝 默认颜色等同于bar=Bar()
ThemeType.LIGHT 蓝黄粉 高亮颜色
ThemeType.DARK 红蓝 黑色背景
ThemeType.CHALK 红蓝绿 黑色背景
ThemeType.ESSOS 红黄 暖色系
ThemeType.INFOGRAPHIC 红蓝黄 偏亮
ThemeType.MACARONS 紫绿
ThemeType.PURPLE_PASSION 粉紫 灰色背景
ThemeType.ROMA 红黑灰 偏暗
ThemeType.ROMANTIC 红粉蓝 淡黄色背景
GDP动态柱状图绘制
列表的sort方法
在前面我们学习过sorted函数,可以对数据容器进行排序。
在后面的数据处理中,我们需要对列表进行排序,并指定排序规则,sorted函数就无法完成了。我们补充学习列表的sort方法。
使用方式:
列表.sort(key=选择排序依据的函数,reverse=True|False)
- 参数key,是要求传入一个函数,表示将列表的每一个元素都传入函数中,返回排序的依据
- 参数reverse,是否反转排序结果,True表示降序,False表示升序
# 准备列表
my_list = [["a", 33], ["b", 55], ["c", 11]]
# 排序,基于带名函数
# def choose_sort_key(element):
# return element[1]
#
# my_list.sort(key=choose_sort_key, reverse=True)
# print(my_list)
# 排序,基于lambda匿名函数
my_list.sort(key=lambda element: element[1], reverse=True)
print(my_list)
# 运行结果
# [["b", 55], ["a", 33], ["c", 11]]
需求分析
简单分析后,发现最终效果图中需要:
- GDP数据处理为亿级
- 有时间轴,按照年份为时间轴的点
- x轴和y轴反转,同时每一年的数据只要前8名国家
- 有标题,标题的年份会动态更改
- 设置了主题为LIGHT
代码展示:
from pyecharts.charts import Bar, Timeline
from pyecharts.options import *
from pyecharts.globals import ThemeType
# 读取数据
f = open("D:/1960-2019全球GDP数据.csv", "r", encoding="GB2312")
data_lines = f.readlines()
# 关闭文件
f.close()
# 删除第一条数据
data_lines.pop(0)
# 将数据转换为字典存储,格式为:
# { 年份: [ [国家, gdp], [国家, gdp], ......], 年份: [ [国家, gdp], [国家, gdp], ......], ......}
# { 1960: [ [美国, 123], [中国, 321], ......], 1961: [ 美国, 123], [中国, 321], ......], ......}
# 先定义一个字典对象
data_dict = { }
for line in data_lines:
year = int(line.split(",")[0]) # 年份
country = line.split(",")[1] # 国家
gdp = float(line.split(",")[2]) # gdp数据
# 如何判断字典里面有没有指定的key呢?
try:
data_dict[year].append([country, gdp])
except KeyError:
data_dict[year] = [ ]
data_dict[year].append([country, gdp])
# 创建时间线对象
timeline = Timeline({"theme": ThemeType.LIGHT})
# 排序年份
sorted_year_list = sorted(data_dict.keys())
for year in sorted_year_list:
data_dict[year].sort(key=lambda element: element[1], reverse=True)
# 取出本年份前8名的国家
year_data = data_dict[year][0:8]
x_data = [ ]
y_data = [ ]
for country_gdp in year_data:
x_data.append(country_gdp[0]) # x轴添加国家
y_data.append(country_gdp[1] / 100000000) # y轴添加gdp数据
# 构建柱状图对象
bar = Bar()
x_data.reverse()
y_data.reverse()
bar.add_xaxis(x_data)
bar.add_yaxis("GDP(亿)", y_data, label_opts=LabelOpts(position="right"))
# 反转x轴和y轴
bar.reversal_axis()
# 设置每一年图表的标题
bar.set_global_opts(
title_opts=TitleOpts(title=f"{year}年全球前8GDP数据")
)
timeline.add(bar, str(year))
# for循环每一年的数据,基于每一年的数据,创建每一年的bar对象
# 在for中,将每一年的bar对象添加到时间线中
# 设置时间线自动播放
timeline.add_schema(
play_interval=500,
is_timeline_show=True,
is_auto_play=True,
is_loop_play=False )
# 绘图
timeline.render("1960-2019全球GDP前8国家.html")