什么是 json
json 是一种轻量级的数据交互格式。可以按照 json 指定的格式去组织和封装数据。
json 本质上是一个带有特定格式的字符串。
json 主要功能
json 就是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互。
各种语言存储数据的容器不尽相同,在 Python 中有字典,而其它语言可能没有字典,这就为不同语言传递数据带来了不便。此时,json 作为一种非常好的中转数据格式,就发挥了作用。
如下图,以 Python 和 C 语言互传数据为例:
json 数据格式
json 本质是字符串,字符串的内容分为两种:
(1) 字典
{"name":"admin","age":18}
(2) 内嵌字典的列表
[{"name":"admin","age":18},{"name":"root","age":16},{"name":"张三","age":20}]
Python 和 Json 数据的相互转化
(1) python 列表 / 字典 ➡ json 字符串:
data = json.dumps(data)
如果有中文,可以带上 ensure_ascii=False 参数来确保中文正常转换。
(2) json 字符串 ➡ python 列表 / 字典:
data = json.loads(data)
#导入json模块
import json
#准备符合json格式要求的python数据
data1 = {"name":"jack","age":20}
data2 = [{"name":"老王","age":16},{"name":"张三","age":20}]
print("把python数据转化为json数据")
#ensure_ascii=False:不使用ascii去转换,而是把内容直接输出,否则中文被转成Unicode字符输出
data1 = json.dumps(data1,ensure_ascii=False)
print(f"data1: {type(data1)}")
print(data1)
data2 = json.dumps(data2,ensure_ascii=False)
print(f"data2: {type(data2)}")
print(data2)
print("把json数据转化为python数据")
data1 = json.loads(data1)
print(f"data1: {type(data1)}")
print(data1)
data2 = json.loads(data2)
print(f"data2: {type(data2)}")
print(data2)
输出结果:
把python数据转化为json数据
data1: <class 'str'>
{"name": "jack", "age": 20}
data2: <class 'str'>
[{"name": "老王", "age": 16}, {"name": "张三", "age": 20}]
把json数据转化为python数据
data1: <class 'dict'>
{'name': 'jack', 'age': 20}
data2: <class 'list'>
[{'name': '老王', 'age': 16}, {'name': '张三', 'age': 20}]
如果要做出数据可视化效果图,可以借助 PyEcharts 模块来完成。
Echarts 是由百度开源的数据可视化模块,凭借良好的交互性、精巧的图表设计,得到了众多开发者的认可。而 Python 是门富有表达力的语言,很适合用于数据处理。当数据分析遇上数据可视化时,PyEcharts 诞生了。
安装 PyEcharts
参照 6. Python 异常、模块与包 中的 3.2
查看官方示例
打开官方画廊:https://gallery.pyecharts.org/#/README
from pyecharts.charts import Line
# 创建一个折线图对象
line = Line()
# 添加x轴数据
line.add_xaxis(["中国","美国","英国"])
# 添加y轴数据(GDP是图例中的字)
line.add_yaxis("GDP",[30,20,10])
# 将代码生成为图像
line.render()
运行完成后,pycharm 左侧项目窗口生成 render.html 文件:
打开 render.html 文件,右上角有浏览器选项,任选一个自己已安装的:
在浏览器中就能看到生成的折线图:
全局配置选项:针对整个图像,如:标题、图例、鼠标、工具箱。
系列配置选项:针对轴数据。
全局配置选项可以通过 set_global_opts 方法来配置,相应的选项和选项的功能如下:
from pyecharts.charts import Line
# 所有可配置的选项都在pyecharts.options中
# TitleOpts:标题配置项功能,LegendOpts:图例配置项,ToolboxOpts:工具箱配置项,VisualMapOpts:视觉映射配置项
from pyecharts.options import TitleOpts, LegendOpts, ToolboxOpts, VisualMapOpts
# 创建一个折线图对象
line = Line()
# 添加x轴数据
line.add_xaxis(["中国","美国","英国"])
# 添加y轴数据
line.add_yaxis("GDP",[30,20,10])
# 设置全局配置项set_global_opts
line.set_global_opts(#关键字参数
# 标题是“GDP展示”,水平居中,距底部1%的距离
title_opts=TitleOpts("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()
所需资料:
链接:https://pan.baidu.com/s/1nI0lFNOxptAmQ3kh5UHMEQ?pwd=sumg
提取码:sumg
要求:读取美日印三国的疫情数据,提取2020年每天的疫情数据,并用折线图显示。
效果图:
代码:
import json
from pyecharts.charts import Line
from pyecharts.options import TitleOpts, LabelOpts, VisualMapOpts
f_us = open("file/折线图数据/美国.txt", "r", encoding="utf-8")
f_jp = open("file/折线图数据/日本.txt", "r", encoding="utf-8")
f_in = open("file/折线图数据/印度.txt", "r", encoding="utf-8")
# 获取文件全部内容
us_data = f_us.read()
jp_data = f_jp.read()
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_data = json.loads(us_data)
jp_data = json.loads(jp_data)
in_data = json.loads(in_data)
# 提取出美国2020年所有的日期,以及每天的确诊病例
us_trend_data = us_data["data"][0]["trend"]
us_x_data = us_trend_data["updateDate"][:314]
us_y_data = us_trend_data["list"][0]["data"][:314]
# 提取出日本2020年每天的确诊病例
jp_trend_data = jp_data["data"][0]["trend"]
jp_y_data = jp_trend_data["list"][0]["data"][:314]
# 提取出印度2020年每天的确诊病例
in_trend_data = in_data["data"][0]["trend"]
in_y_data = in_trend_data["list"][0]["data"][:314]
# 图表对象
line = Line()
# 添加x轴数据,三国公用即可
line.add_xaxis(us_x_data)
# 添加y轴数据
# label_opts是一个系列配置选项,用于配置折线上节点的数据是否显示
line.add_yaxis("美国",us_y_data,label_opts=LabelOpts(is_show=False))
line.add_yaxis("日本",jp_y_data, label_opts=LabelOpts(is_show=False))
line.add_yaxis("印度",in_y_data, label_opts=LabelOpts(is_show=False))
# 设置全局选项
line.set_global_opts(
# 标题设置
title_opts= TitleOpts("2020 年美日印三国新冠确诊病例趋对比",pos_left="center", pos_bottom="1%"),
)
# 调用render方法,生成图表
line.render()
# 关闭文件对象
f_us.close()
f_jp.close()
f_in.close()
from pyecharts.charts import Map
from pyecharts.options import VisualMapOpts
# 创建地图对象
map = Map()
# 准备数据
data = [
("北京", 4),
("上海", 20),
("山东", 90),
("江西", 200)
]
# 添加数据
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()
上面代码也会生成一个 render.html 文件,在浏览器中的查看方式与折线图相同。
要求:各省份确诊人数所在的范围不同,则显示的颜色不同。鼠标悬停于某个省份时,显示该省份的确诊人数。
效果图:
代码:
import json
from pyecharts.charts import Map
from pyecharts.options import VisualMapOpts
# 文件读取
f = open("file/地图数据/疫情.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 = []
# 遍历各省,获取每个省份的名称、确诊人数, 添加到data_list
for provience_data in province_data_list:
province_name = provience_data["name"]
province_confirm = provience_data["total"]["confirm"]
data_list.append((province_name, province_confirm))
# 创建地图对象
map = Map()
# 添加数据,第三个参数如果不写,构建的也是中国地图
map.add("疫情人数", data_list, "china")
# 设置全局配置选项
map.set_global_opts(
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"}
]
)
)
# 显示地图, 自定义生成的html文件名称
map.render("全国疫情地图.html")
要求:各城市确诊人数所在的范围不同,则显示的颜色不同。鼠标悬停于某个城市时,显示该城市的确诊人数。
效果图:
代码:
import json
from pyecharts.charts import Map
from pyecharts.options import VisualMapOpts
# 文件读取
f = open("file/地图数据/疫情.txt", "r", encoding="utf-8")
data = f.read()
f.close()
# 将json字符串转换成python字典
data_dict = json.loads(data)
# 获取河南各城市的数据
city_data_list = data_dict["areaTree"][0]["children"][3]["children"]
# 用于存放元组,每个元组都含有一个城市的数据(城市名称, 确诊人数)
data_list = []
# 遍历各城市,获取每个城市的名称、确诊人数, 添加到data_list
for city_data in city_data_list:
# 一定要加市,否则疫情地图不显示颜色
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(
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"}
]
)
)
# 显示地图, 自定义生成的html文件名称
map.render("河南省疫情地图.html")
通过 Bar 构架基础柱状图。
from pyecharts.charts import Bar
# 创建Bar对象
bar = Bar()
# 添加x轴数据
bar.add_xaxis(["中国", "美国", "英国"])
# 添加y轴数据, "GDP"为y轴数据的名字
bar.add_yaxis("GDP", [30, 20, 10])
# 显示(绘图)
bar.render("基础柱状图.html")
反转 x、y 轴:可以使用 reversal_axis 方法。
效果:
代码:
from pyecharts.charts import Bar
# 创建Bar对象
bar = Bar()
# 添加x轴数据
bar.add_xaxis(["中国", "美国", "英国"])
# 添加y轴数据, "GDP"为y轴数据的名字
bar.add_yaxis("GDP", [30, 20, 10])
# x、y轴反转
bar.reversal_axis()
# 显示(绘图)
bar.render("基础柱状图.html")
指定标签的显示位置:可以看到,上图中的数据标签(10,20,30)都是在柱状图上方显示。如果向让它们在右侧显示,可以在添加 y 轴数据的同时来指定标签的显示位置。
效果:
代码:
from pyecharts.charts import Bar
from pyecharts.options import LabelOpts
# 创建Bar对象
bar = Bar()
# 添加x轴数据
bar.add_xaxis(["中国", "美国", "英国"])
# 添加y轴数据, "GDP"为y轴数据的名字; 并且让数据标签在右侧显示
bar.add_yaxis("GDP", [30, 20, 10], label_opts=LabelOpts(position="right"))
# x、y轴反转
bar.reversal_axis()
# 显示(绘图)
bar.render("基础柱状图.html")
Timeline()-时间线:普通的柱状图很难动态的描述一个趋势性的数据,pyecharts 就提供了一种解决方案——时间线。如果说一个 Bar、Line 对象是一张图表的话,时间线就是创建一个一维的 x 轴,轴上每一个点就是一个图表对象。
中美英三国 GDP 动态演示效果:
代码:
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, 20, 10], 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", [40, 30, 20], 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
)
# 绘图
timeline.render("基础时间线柱状图.html")
附:主题颜色
列表的 sort 方法
在前面学习过 sorted 函数,可以对数据容器进行排序。
在后面的数据处理中,需要对列表进行排序,并指定排序规则,sorted 函数就无法完成了。这时就需要列表的 sort 方法。
使用方式:
列表.sort(key = 选择排序依据的函数,reverse = True | False)
参数 key:是要求传入的一个函数,表示将列表的每个元素都传入函数中,返回排序的依据。传入的函数有两种形式:普通带名函数、lambda 函数。
参数 reverse:是否反转排序结果,True 表示降序,False 表示升序。
(1) key 传入普通带名函数:
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)
(2) key 传入 lambda 函数:
my_list = [["a", 33], ["b", 55], ["c", 11]]
# 排序,指定排序的依据、降序
my_list.sort(key=lambda element:element[1], reverse=True)
print(my_list)
输出结果:
[['b', 55], ['a', 33], ['c', 11]]
1960~2019 年各国 GDP 动态柱状图
效果:
代码:
from pyecharts.charts import Bar, Timeline
from pyecharts.options import LabelOpts, TitleOpts
from pyecharts.globals import ThemeType
f = open("file/动态柱状图数据/1960-2019全球GDP数据.csv", "r", encoding="GB2312")
# 逐行读取并保存在列表中,每行是列表的一个元素
data_lines = f.readlines()
f.close()
# 去掉第一行
data_lines.pop(0)
# 用于保存各年份内,各国的GDP数据
data_dict = {}
# 将各年份内,各国的GDP数据保存在字典data_dict中
for line in data_lines:#data_lines是一个列表
year = int(line.split(",")[0])
country = line.split(",")[1]
#gdp以亿为单位
gdp = float(line.split(",")[2]) / 100000000
try:
# 字典以year为key,year是列表,下面为该列表添加元素
data_dict[year].append([country, gdp])
except KeyError:
# 若还没有该年份的key
data_dict[year] = []
data_dict[year].append([country, gdp])
# 创建时间线对象,设置主题(颜色)
timeline = Timeline(
{"theme":ThemeType.LIGHT}
)
for year in data_dict:
# 每年的都把各国按照gdp从大到小的顺序排序
data_dict[year].sort(key=lambda element:element[1], reverse=True)
# 取排序后的top8
year_data = data_dict[year][:8]
# 准备x、y轴所需数据
x_data = []
y_data = []
for country_data in year_data:
x_data.append(country_data[0])
y_data.append(country_data[1])
x_data.reverse()#元素反转,使gdp高的先显示
y_data.reverse()
# 创建柱状图对象
bar = Bar()
#为x轴添加数据
bar.add_xaxis(x_data)
#为y轴添加数据,y轴数据名称"GDP(亿)",数据标签在右侧显示
bar.add_yaxis("GDP(亿)", y_data, label_opts=LabelOpts(position="right"))
# x、y轴反转
bar.reversal_axis()
# 柱状图标题
bar.set_global_opts(
title_opts=TitleOpts(f"{year}年各国GDP(TOP8)")
)
# 将柱状图添加进时间线,方法的第二个参数是str类型,是时间点的名称
timeline.add(bar, str(year))
timeline.add_schema(
#时间线默认显示,可以不设置可见性
play_interval=1000,#播放间隔时间1000ms
is_auto_play=True,#是否自动播放
is_loop_play=False#是否循环播放
)
# 绘图
timeline.render("1960-2019GDP前八名的国家.html")