案例学习引自黑马程序员,基于pyecharts,制作好看的折线图、动态柱状图。pyecharts 是一个用于生成 Echarts 图表的类库。echarts 是百度开源的一个数据可视化 JS 库,主要用于数据可视化。所以pyecharts就是python和echarts 的结合,用Python语言实现数据可视化。
关于这部分内容,网上有很多很详细的笔记,这里就不重复了,有需要的可以下载知乎烟云的笔记,地址如下:
简单谈下自己的学习感悟。
1、效果图都非常好看,而且在数据处理后易于实现。折线图可以用于毕业论文,统计报表,地图可视化可用于全国-省市的统计数据呈现,动态柱状图可以制作激动人心的国家发展短视频。
2、学习的难点在于如何使用json进行数据转化。json的语法格式相当于由Python的字典或者内嵌字典的列表转换成的字符串。将json数据转化为python数据使用json.dumps
,将python数据转化为json数据使用json.loads
。
3、json数据层级分析可以使用第三方网站工具,例如:
JSON 在线解析 | 菜鸟工具
4、所有的图表都可以通过全局配置选项(set_global_opts方法)对标题、图例、工具箱等进行配置。
折线图开发
"""
演示可视化需求1:折线图开发
"""
import json
from pyecharts.charts import Line
from pyecharts.options import TitleOpts, LabelOpts
# 处理数据
f_us = open("D:/test/1-10-3/美国.txt", "r", encoding="UTF-8")
us_data = f_us.read() # 美国的全部内容
f_jp = open("D:/test/1-10-3/日本.txt", "r", encoding="UTF-8")
jp_data = f_jp.read() # 日本的全部内容
f_in = open("D:/test/1-10-3/印度.txt", "r", encoding="UTF-8")
in_data = f_in.read() # 印度的全部内容
# 去掉不合JS0N规范的开头
us_data = us_data.replace('jsonp_1629344292311_69436(', '')
jp_data = jp_data.replace('jsonp_1629350871167_29498(', '')
in_data = in_data.replace('jsonp_1629350745930_63180(', '')
# 去掉不合JS0N规范的结尾
us_data = us_data[:-2]
jp_data = jp_data[:-2]
in_data = in_data[:-2]
# JS0N转Python字典
us_dict = json.loads(us_data)
jp_dict = json.loads(jp_data)
in_dict = json.loads(in_data)
# print(type(us_dict))
# print(us_dict)
# 获取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']
# print(type(trend_data))
# print(trend_data)
# 获取日期数据,用于x轴,取2020年(根据数据信息需要取到314)
# - 解释: trend_data['updateDate']表示将字典中关键字为'updateDate'的数据取出来 切片[:314]是将前面313个数据取出来
us_x_data = us_trend_data['updateDate'][:314] # 查看文档后取314
jp_x_data = jp_trend_data['updateDate'][:315] # 查看文档后取315
in_x_data = in_trend_data['updateDate'][:269] # 查看文档后取269
# print(x_data)
# 获取确认数据,用于y轴,取2020年(到314下标结束)
us_y_data = us_trend_data['list'][0]['data'][:314]
jp_y_data = jp_trend_data['list'][0]['data'][:315]
in_y_data = in_trend_data['list'][0]['data'][:269]
# print(y_data)
# 生成图表
line = Line() # 构建折线图对象
# 添X抽数据
line.add_xaxis(us_x_data)
line.add_xaxis(jp_x_data)
line.add_xaxis(in_x_data)
# 添心抽数据
line.add_yaxis("美国确诊人数", us_y_data,
label_opts=LabelOpts(is_show=False)) # 添加美国的y轴数摇 label_opts=LabelOpts(is_show=False):标签不显示数字
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()
全国疫情可视化地图开发
"""
演示全国疫情可视化地图开发
"""
import json
from pyecharts.charts import Map
from pyecharts.options import TitleOpts, VisualMapOpts
# 读取数据文件
f = open("D:/test/1-11/疫情.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"] # 省份名称
if province_name == "北京" or province_name == "上海" \
or province_name == "重庆" or province_name == "天津":
province_name += '市'
elif province_name == "内蒙古":
province_name = "内蒙古自治区"
elif province_name == "广西":
province_name = "广西壮族自治区"
elif province_name == "宁夏":
province_name = "宁夏回族自治区"
elif province_name == "西藏":
province_name = "西藏自治区"
elif province_name == "新疆":
province_name = "新疆维吾尔自治区"
else:
province_name += '省'
province_confirm = province_data["total"]["confirm"] # 确诊人数
data_list.append((province_name, province_confirm))
# print(data_list) # 中途用来验证数据是否正确
# 创建地图对象
map = Map()
# 添加数据
map.add("各省份确诊人数", data_list, "china")
# 设置全局配置,定制分段的视觉映射
map.set_global_opts(
title_opts=TitleOpts(title="全国疫情地图", pos_left="center"),
visualmap_opts=VisualMapOpts(
is_show=True, # 是否显示
is_piecewise=True, # 是否分段
pieces=[
{"min": 1, "max": 99, "label": "1-99人", "color": "#CCFFFF"},
{"min": 100, "max": 999, "label": "100-999人", "color": "#FFFF99"},
{"min": 1000, "max": 4999, "label": "1000-4999人", "color": "#FF9966"},
{"min": 5000, "max": 9999, "label": "5000-9999人", "color": "#FF6666"},
{"min": 10000, "max": 99999, "label": "10000-99999人", "color": "#CC3333"},
{"min": 100000, "label": "100000+", "color": "#990033"}
] # 给各分段设上颜色
)
)
# 绘图
map.render("全国疫情地图.html")
省级疫情地图开发
"""
演示河南省疫情地图开发
"""
import json
from pyecharts.charts import Map
from pyecharts.options import TitleOpts, VisualMapOpts
# 读取文件
f = open("D:/test/1-11/疫情.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 = 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))
# print(data_list) 用于中途测试数据
# 手动添加济源市的数据
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, "label": "1-99人", "color": "#CCFFFF"},
{"min": 100, "max": 999, "label": "100-999人", "color": "#FFFF99"},
{"min": 1000, "max": 4999, "label": "1000-4999人", "color": "#FF9966"},
{"min": 5000, "max": 9999, "label": "5000-9999人", "color": "#FF6666"},
{"min": 10000, "max": 99999, "label": "10000-99999人", "color": "#CC3333"},
{"min": 100000, "label": "100000+", "color": "#990033"}
] # 给各分段设上颜色
)
)
# 绘图
map.render("河南省疫情地图.htm")
GDP动态柱状图开发
"""
演示第三个图表:GDP动态柱状图开发
"""
from pyecharts.charts import Bar, Timeline
from pyecharts.options import LabelOpts, TitleOpts, TimelineCheckPointerStyle
from pyecharts.globals import ThemeType
# ----------------------------1.获取数据------------------------
# 读取数据
f = open("D:/test/1-12/1960-2019全球GDP数据.csv", "r", encoding="GB2312")
data_lines = f.readlines() # 按行读取每一行数据
# 关闭文件
f.close()
# 删除第一行数据
data_lines = data_lines[1:] # 或 data_lines.pop(0)
# print(data_lines) # 中途测试代码
# -----------------------------2.处理数据------------------------
# 每行数据都是字符串,很难处理。 故将数据转换成字典存储,格式为:
# { 年份: [ [国家, gdp], [国家,gdp], ...... ], 年份: [ [国家, gdp], [国家,gdp], ...... ], ...... }
# 按照这样的格式便于处理,按照年份作为时间线,国家和gdp为一个条形图中一个柱的两个参数
# 2.1 先定义一个字典对象,获取数据
data_dict = {}
# 2.2 把数据整理好并放入字典中
for line in data_lines:
line.strip() # 去掉换行符
year = int(line.split(",")[0]) # 年份
country = line.split(",")[1] # 国家
gdp = float(line.split(",")[2]) # gdp数据
# 在给字典添加每一个元素的键值对中的值时,需判断这个值[国家, gdp]是否是这一年中所加的第一个数据。
# 如果是第一个,那么说明还没有加入对应的键值对的关键字(即年份)
# --> 如何判断字典里面有没有指定的key呢?
try:
data_dict[year].append([country, gdp]) # 年份不存在,在关键字year下继续添加[country, gdp]
except KeyError:
data_dict[year] = [] # 年份不存在,加入新的键值对
data_dict[year].append([country, gdp])
# print(data_dict) # 中途测试代码
# -----------------------------3.绘图------------------------
# 3.1 排序年份 (字典是靠键值对的关键字查询数据的,没有顺序)
sorted_year_list = sorted(data_dict.keys())
# print(sorted_year_list) # 中途测试代码
# 3.2 取出每年gdp前8的国家,然后构建每一年的柱状图,并按时间线设置好对应的柱状图
# 创建时间线对象,并设置主题
timeline = Timeline({"theme": ThemeType.LIGHT})
for year in sorted_year_list:
# 将每一年的各个国家的gdp按照从大到小顺序进行排序
data_dict[year].sort(key=lambda element: element[1], reverse=True)
# 取出本年份前8的国家
year_data = data_dict[year][:8]
x_data = [] # 用来存放当年x轴数据
y_data = [] # 用来存放当年y轴数据
for country_gdp in year_data:
x_data.append(country_gdp[0]) # 获取当年gdp第country_gdp名的国家
y_data.append(country_gdp[1] / 1e8) # 获取当年gdp第country_gdp名的gdp,单位(亿)
# 构建柱状图
bar = Bar()
x_data.reverse() # 反转数据,将前8按照gdp从小到大的顺序进行排序 --> 柱状图的图形的从上到下,依次是gdp从大到小的国家
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))
# 3.3 设置时间线自动播放
timeline.add_schema(
play_interval=300, # 自动播放的时间阿隔,单位毫砂
is_timeline_show=True, # 是否在自动播放的时候,显示时间线
is_auto_play=True, # 是否自动播放
is_loop_play=False, # 是否循环自动播放
label_opts=LabelOpts(is_show=True,color="#4169E1")
)
# 3.4 绘图
timeline.render("1960-2019年全球GDP前8的国家.html")