Python基础教程08:深入了解JSON和Pyecharts模块,学习折线图、地图、柱状图的绘制方法

一 python变量和json数据的相互转化

json就是 一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互、类似于:
国际通用语言 -英语。

import json
if __name__ == '__main__':
    # 1. 将python变量转成json(列表->json)
    # 准备列表,列表内每一个元素都是字典,将其转换为JSON
    data = [{"name": "张大山", "age": 11}, {"name": "王大锤", "age": 13}, {"name": "赵小虎", "age": 16}]
    json_str = json.dumps(data)
    print(type(json_str))#<class 'str'>
    print(json_str)
    json_str = json.dumps(data, ensure_ascii = False)
    print(json_str)

    print("====================================")

    # 2. 将python变量转成json(字典->json)
    # 准备字典,将字典转换为JSON
    d = {"name": "周杰轮", "addr": "台北"}
    json_str = json.dumps(d, ensure_ascii = False)
    print(type(json_str))#<class 'str'>
    print(json_str)

    print("====================================")

    # 3. 将json转成python变量(json(实际是字符串)->列表)
    s = '[{"name": "张大山","age": 11}, {"name": "王大锤", "age": 13}, {"name": "赵小虎", "age": 16}]'
    l = json.loads(s)
    print(type(l))#<class 'list'>
    print(l)

    print("====================================")

    # 4. 将json转成python变量(json(实际是字符串)->字典)
    # 这里与第3点区别是,3无法直接转字典,而4能够直接转字典,所以4优先转成字典
    s = '{"name": "周杰轮", "addr": "台北"}'
    d = json.loads(s)
    print(type(d))#<class 'dict'>
    print(d)

二 pyecharts模块简介

pyecharts模块 :如果想要 做出数据可视化效果图,可以借助pyecharts模块来完成。
概况:
Echarts是个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可.而Python是门富有表达力的语言,很适合用于数据处理.当数据分析遇上数据可视化时pyecharts诞生了。

官网:pyecharts.org。
可以选择语言进行查看pyecharts的文档。

pyecharts还有一个画廊功能:gallery.pyecharts.org。
pyecharts模块的安装:

pip install pyecharts

三 pyecharts的入门使用

pyecharts有哪些配置选项。
pyecharts模块中有 很多的配置选项,常用到2个类别的选项:

  • 全局配置选项(这里会用到)。set_global_opts,就是帮我们设置标题等内容。
  • 系列配置选项。
  • from pyecharts.charts import Line
    from  pyecharts.options import TitleOpts
    from  pyecharts.options import LegendOpts
    from  pyecharts.options import ToolboxOpts
    from  pyecharts.options import VisualMapOpts
    if __name__ == '__main__':
        # 导包,导入Line功能构建折线图对象
    
        # 得到折线图对象
        line = Line()
        # 添加x轴数据
        line.add_xaxis(["中国", "美国", "英国"])
        # 添加y轴数据
        line.add_yaxis("GDP", [30, 20, 10])
    
        line.set_global_opts(
            title_opts=TitleOpts(True, "GDP展示", pos_left= "center", pos_bottom = "1%"),   #添加标题
            legend_opts=LegendOpts(is_show=True),#添加图例
            toolbox_opts=ToolboxOpts(is_show=True),#添加工具箱
            visualmap_opts=VisualMapOpts(is_show=True)
    
        )
    
        # 生成图表
        line.render()
    
    
    

    运行后会生成render.html,我们双击打开它。

    然后在pycharm右上角选择浏览器打开。


    图例的意思可以看Echarts legend属性使用理解。

    四 数据准备

    请自行找资料,或者找我。

    五 生成折线图

    首先打开网页http://www.ab173.com/gongju/json/jsonviewernew.php。通过它我们方便观察长json串的视图,方便在代码取数据。
    以美国.txt为例,将所有内容拷贝到上面的网站,
    然后:
    去掉开头的内容:

    jsonp_1629344292311_69436(
    


    去掉末尾的两个元素:

    );
    

    然后选择格式化,数据变成下图。

    再选择视图,就是下图,这样我们就方便观察json数据了。

    当然,如果你眼力好,可以直接看美国.txt的内容,然后在代码中操作,但是不建议,因为直接看这么长的字符串是很难的。

    代码:

    """
    演示可视化需求1:折线图开发
    """
    import json
    from pyecharts.charts import Line
    from pyecharts.options import TitleOpts, LabelOpts
    
    # 处理数据
    # 1. 读取数据
    f_us = open("C:/Users/Administrator/Desktop/Py/资料/可视化案例数据/折线图数据/美国.txt", "r", encoding="UTF-8")
    us_data = f_us.read()   # 美国的全部内容
    
    f_jp = open("C:/Users/Administrator/Desktop/Py/资料/可视化案例数据/折线图数据/日本.txt", "r", encoding="UTF-8")
    jp_data = f_jp.read()   # 日本的全部内容
    
    f_in = open("C:/Users/Administrator/Desktop/Py/资料/可视化案例数据/折线图数据/印度.txt", "r", encoding="UTF-8")
    in_data = f_in.read()   # 印度的全部内容
    
    # 2. 去掉开头和结尾的非json内容
    # 去掉不合JSON规范的开头(这是它自己加的,一般实际开发只有纯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规范的结尾(这是它自己加的,一般实际开发只有纯json串)
    # -2 代表去掉末尾的最后两个元素,因为切片不包括末尾的下标
    us_data = us_data[:-2]
    jp_data = jp_data[:-2]
    in_data = in_data[:-2]
    
    # 3. JSON转Python字典
    us_dict = json.loads(us_data)
    jp_dict = json.loads(jp_data)
    in_dict = json.loads(in_data)
    
    # 4. 获取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(f"trend key数据类型: {type(us_trend_data)}")# trend key数据类型: <class 'dict'>
    
    # 获取日期数据,用于x轴,取2020年(到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]
    print(f"updateDate数据类型: {type(us_x_data)}")# us_x_data数据类型: <class 'list'>
    
    # 获取确认数据,用于y轴,取2020年(到314下标结束. 实际好像不是314,我不太确定它那个数字的含义例如20462501,不过我们不关注)
    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]
    print(f"y轴数据类型: {type(us_y_data)}")# y轴数据类型: <class 'list'>
    
    # 生成图表
    line = Line()       # 构建折线图对象
    # 添加x轴数据
    line.add_xaxis(us_x_data)   # x轴是公用的,所以使用一个国家的数据即可
    # 添加y轴数据
    # label_opts=LabelOpts(is_show=False)的作用是去掉折线图的数字,避免影响观看
    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()
    

    结果:

    取数据对应视图:

    下图实际好像不是314,我不太确定它那个数字的含义,例如20462501,不过我们不关注,因为实际开发时我们肯定知道对应的年份数据。

    六 数据可视化案例-基础地图使用

    """
    演示地图可视化的基本使用
    """
    from pyecharts.charts import Map
    from pyecharts.options import VisualMapOpts
    
    # 准备地图对象
    map = Map()
    # 准备数据
    data = [
    #     ("北京", 99),
    #     ("上海", 199),
    #     ("湖南", 299),
    #     ("台湾", 399),
    #     ("广东", 499)
    # ]
    data = [
        ("北京市", 99),
        ("上海市", 199),
        ("湖南省", 299),
        ("台湾省", 399),
        ("广东省", 499)
    ]
    # 添加数据(data是列表,元素是元祖)
    map.add("测试地图", data, "china")
    
    # 设置全局选项
    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("基础地图.html")
    

    注意,如果data的省或者直辖市不改成和地图一样的名字,是没有颜色的。

    七 全国疫情地图构建

    """
    演示全国疫情可视化地图开发
    """
    import json
    from pyecharts.charts import Map
    from pyecharts.options import *
    
    # 1. 读取数据文件
    f = open("C:/Users/Administrator/Desktop/Py/资料/可视化案例数据/地图数据/疫情.txt", "r", encoding="UTF-8")
    data = f.read()     # 全部数据
    # 关闭文件
    f.close()
    
    # 2. 取到各省数据
    # 将字符串json转换为python的字典
    data_dict = json.loads(data)        # 基础数据字典
    # 从字典中取出省份的数据
    province_data_list = data_dict["areaTree"][0]["children"]
    
    # 处理省份名字,我们的province_name变量必须要与地图的名字匹配,否则不显示颜色.
    def handle_pro_name(name):
        tmp = None
        if name == "上海":
            tmp = "上海市"
        elif name == "香港":
            tmp = "香港特别行政区"
        elif name == "天津":
            tmp = "天津市"
        elif name == "北京":
            tmp = "北京市"
        elif name == "广西":
            tmp = "广西壮族自治区"
        elif name == "重庆":
            tmp = "重庆市"
        elif name == "澳门":
            tmp = "澳门特别行政区"
        elif name == "内蒙古":
            tmp = "内蒙古自治区"
        elif name == "宁夏":
            tmp = "宁夏回族自治区"
        elif name == "西藏":
            tmp = "西藏自治区"
        elif name == "新疆":
            tmp = "新疆维吾尔自治区"
        else:
            tmp = name + "省"
        return tmp
    
    # 3. 组装每个省份和确诊人数为元组,并各个省的数据都封装入列表内
    data_list = []      # 绘图需要用的数据列表
    for province_data in province_data_list:
        province_name = province_data["name"]                   # 省份名称
        province_name = handle_pro_name(province_name)
        province_confirm = province_data["total"]["confirm"]    # 确诊人数
        data_list.append((province_name, province_confirm))     # 上节说过,map.add要的是列表,列表的元素是元祖
        #print((province_name, province_confirm))
    
    # 4. 创建地图对象
    map = Map()
    
    # 5. 添加数据
    map.add("各省份确诊人数", data_list, "china")
    
    # 6. 设置全局配置,定制分段的视觉映射
    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~9999人", "color": "#FFFF99"},
                {"min": 1000, "max": 4999, "lable": "1000~4999人", "color": "#FF9966"},
                {"min": 5000, "max": 9999, "lable": "5000~99999人", "color": "#FF6666"},
                {"min": 10000, "max": 99999, "lable": "10000~99999人", "color": "#CC3333"},
                {"min": 100000, "lable": "100000+", "color": "#990033"},
            ]
        )
    )
    
    # 7. 绘图
    map.render("全国疫情地图.html")
    
    
    

    结果:
    这里注意,新版本的pyecharts(也可能是python解释器的版本)的地图名字,如果和代码中的province_name值不一样,会无法显示颜色,所以我自行加了一个函数handle_pro_name进行处理。

    province_data_list = data_dict[“areaTree”][0][“children”]的结构:

    province_data的结构:

    八 河南省疫情地图绘制

    """
    演示河南省疫情地图开发
    """
    import json
    from pyecharts.charts import Map
    from pyecharts.options import *
    
    # 读取文件
    f = open("C:/Users/Administrator/Desktop/Py/资料/可视化案例数据/地图数据/疫情.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))
    
    # 手动添加济源市的数据,因为疫情.txt没有
    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~9999人", "color": "#FFFF99"},
                {"min": 1000, "max": 4999, "lable": "1000~4999人", "color": "#FF9966"},
                {"min": 5000, "max": 9999, "lable": "5000~99999人", "color": "#FF6666"},
                {"min": 10000, "max": 99999, "lable": "10000~99999人", "color": "#CC3333"},
                {"min": 100000, "lable": "100000+", "color": "#990033"},
            ]
        )
    )
    
    # 绘图
    map.render("河南省疫情地图.html")
    
    
    结果:
    

    九 基础柱状图构建

    """
    演示基础柱状图的开发
    """
    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")
    
    # 反转x轴和y轴
    
    # 设置数值标签在右侧
    
    

    翻转时(调用bar.reversal_axis()):

    不翻转时:
    但是不翻转的话,我们看到柱状图右边30,20,10,没有放在柱状图的顶部,所以我们建议翻转一下。

    十 基础时间线柱状图绘制

    """
    演示带有时间线的柱状图开发
    """
    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()
    
    # 构建时间线对象
    # theme可以修改柱的颜色
    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")
    

    我们看到,下图实际上会根据时间线进行滚动。

    十一 动态GDP柱状图绘制

    """
    演示第三个图表:GDP动态柱状图开发
    """
    from pyecharts.charts import Bar, Timeline
    from pyecharts.options import *
    from pyecharts.globals import ThemeType
    
    # 1. 读取数据
    f = open("C:/Users/Administrator/Desktop/Py/资料/可视化案例数据/动态柱状图数据/1960-2019全球GDP数据.csv", "r", encoding="GB2312")
    data_lines = f.readlines()
    # 关闭文件
    f.close()
    
    # 2. 删除第一条数据(第一条是无用的内容year,GDP,rate标志)
    data_lines.pop(0)
    
    # 3. 将数据转换为字典存储,格式为:
    # { 年份: [ [国家, 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数据,加上float是为了将带有科学计数法(5.433E+11)的转成正常的数值
        # 如何判断字典里面有没有指定的key呢? 通过异常
        try:
            data_dict[year].append([country, gdp])
        except KeyError:
            data_dict[year] = []
            data_dict[year].append([country, gdp])
    # print(data_dict[1960])
    
    # 4. 创建时间线对象
    timeline = Timeline({"theme": ThemeType.LIGHT})
    
    # 5. 排序年份
    sorted_year_list = sorted(data_dict.keys())
    
    # 6. 将每一年的数据创建成对应的bar,然后每个bar都添加到时间线.
    for year in sorted_year_list:
        data_dict[year].sort(key=lambda element: element[1], reverse=True) # 将年份里的列表按照gdp值大小进行排序
        year_data = data_dict[year][0:8] # 取出本年份前8名的国家和gdp
        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轴的国家排序翻转,以及将y轴的gdp数据翻转,是为了gdp高的放在柱状图最上面,gdp低的放在最下面
        x_data.reverse()
        y_data.reverse()
        # 添加x轴和y轴到柱状图.
        bar.add_xaxis(x_data)
        bar.add_yaxis("GDP(亿)", y_data, label_opts=LabelOpts(position="right")) # position="right"的作用是将便签放在右边
        # 反转x轴和y轴(上面是将内容翻转,这里是单纯的x轴和y轴调换)
        bar.reversal_axis()
    
        # 动态设置每一年的图表的标题
        bar.set_global_opts(
            title_opts=TitleOpts(title=f"{year}年全球前8GDP数据")
        )
        # 添加每一年的柱状图到时间线
        timeline.add(bar, str(year))
    
    # 7. 设置时间线自动播放
    timeline.add_schema(
        play_interval=1000,
        is_timeline_show=True,
        is_auto_play=True,
        is_loop_play=False
    )
    
    # 8. 绘图
    timeline.render("1960-2019全球GDP前8国家.html")
    
    

    结果:

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python基础教程08:深入了解JSON和Pyecharts模块,学习折线图、地图、柱状图的绘制方法

    发表评论