案例学习引自黑马程序员,基于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")