本实验通过爬虫等技术手段获取山西省各市全年的大气主要污染物监测数据,为了更好地观察结果对大气污染数据进行污染物数据变化展示。由于时间有限(其实也不是做这个的,就是单纯感兴趣),因此就实现了比较简单的数据展示,后续有时间的话,在补充一些网页美化的内容。
数据介绍:
获得的数据施加跨度为5年,每年每天有24条数据(即每个小时一条),共有N个站点,为了简要可视化,从中抽取了部分数据作为样例,进行可视化。
样例数据如下图:
列:各地区
行:时间
(注:根据自己的的需要行列代表的因素可进行调整,只要在代码里面相互对应就好,当然这是一个表,也可以读取多个表。)
// 完整代码
import pandas as pd
import pandas as pd
import openpyxl
from pyecharts.faker import Faker
from pyecharts.globals import ThemeType
import pyecharts.options as opts
from pyecharts.commons.utils import JsCode
from pyecharts.charts import Timeline, Grid, Bar, Map, Pie, Line, Page
'''
1.导入相关的库,主要是使用pyecharts.Charts
2.制定相应的数据格式(两种方式:一种是excel适配代码,另一种是代码适配excel)
3.编写相应的绘图代码:柱状图、饼图、地图等等,操作手册:https://pyecharts.org/#/zh-cn/intro
4.位置、大小调整,部分地方可能主要设定指定的像素大小,所以在参数设置的地方进行设置
5.时间轮播图,时间轮播设置
'''
data = pd.read_excel(r'污染物可视化数据(样例).xlsx', engine='openpyxl', index_col=0)#名字为“污染物可视化数据(样例).xlsx”的数据和py文件存在同一文件夹下
days = list(data.keys()) # 获取列名
citys = list(data.index) # 获取索引行名
# citys = [city.replace('省', '').replace('市', '').replace('自治区', '') for city in citys]
datas = []
for y in days:
dict_day = {}
dict_day['time'] = y # 字典的赋值
data_list = [[i, j] for i, j in zip(citys, list(data[y]))]
dict_day['data'] = data_list
datas.append(dict_day)
def get_day_chart(day: int):
map_data = [i['data'] for i in datas if i['time'] == day][0]
map_data = sorted(map_data, key=(lambda x: x[1]), reverse=True)[:10] # 关键点(对柱形图展示有帮助)(一个排序)
min_data, max_data = (
min([d[1] for d in map_data]),
max([d[1] for d in map_data])
)
# 绘制地图
map_chart = (
Map(init_opts=opts.InitOpts(width="600px",
height="300px", theme=ThemeType.DARK))
.add(series_name='', data_pair=map_data, maptype="山西")
# .add_coordinate("1081A", 112.522, 37.8873)
.set_global_opts(
title_opts=opts.TitleOpts(
title="山西省各市{}日CO污染情况".format(day),
subtitle="单位:暂定",
pos_left="center",
pos_top="top",
title_textstyle_opts=opts.TextStyleOpts(font_size=25, color='white')
),
visualmap_opts=opts.VisualMapOpts(dimension=0, is_show=False, min_=min_data,
max_=max_data,
pos_top="top", pos_left="90%", pos_bottom="90%",
range_text=["High", "Low"],
range_color=["lightskyblue", "yellow", "orangered"],
textstyle_opts=opts.TextStyleOpts(color="#ddd"),
)
)
)
# 绘制柱图
bar_x_data = [x[0] for x in map_data]
bar_y_data = [x[1] for x in map_data]
# print(bar_y_data)
bar = (
Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK))
.add_xaxis(xaxis_data=bar_x_data)
.add_yaxis(
series_name="",
y_axis=bar_y_data,
label_opts=opts.LabelOpts(
is_show=True, position="right", formatter="{b}: {c}" # 关键知识点,解决标签显示不全的问题
)
)
.reversal_axis()
.set_global_opts(
visualmap_opts=opts.VisualMapOpts(
dimension=0, # 不知道为什么,有了这个,这个视觉配置项起作用了
pos_left="10",
pos_top="150",
range_text=["High", "Low"],
range_color=["lightskyblue", "yellow", "orangered"],
textstyle_opts=opts.TextStyleOpts(color="#ddd"),
min_=min_data,
max_=max_data
)
)
)
# 绘制饼图
pie_data = [[x[0], x[1]] for x in map_data]
pie = (
Pie(init_opts=opts.InitOpts(theme=ThemeType.DARK))
.add(
series_name="占比",
data_pair=pie_data,
radius=["15%", "40%"],
center=["79%", "80%"], # 饼图的中心(圆心)坐标,数组的第一项是横坐标,第二项是纵坐标
# 默认设置成百分比,设置成百分比时第一项是相对于容器宽度,第二项是相对于容器高度
itemstyle_opts=opts.ItemStyleOpts(
border_width=1, border_color="rgba(0,0,0,0.3)"
),
)
.set_global_opts(
tooltip_opts=opts.TooltipOpts(is_show=True, formatter="{b} {d}%"), # 关键点:提示框显示百分比
legend_opts=opts.LegendOpts(is_show=False),
)
)
# 绘制趋势图
qs1 = [x[0] for x in map_data]
qs2 = [x[1] for x in map_data]
line = (
Line(init_opts=opts.InitOpts(theme=ThemeType.DARK))
.add_xaxis(xaxis_data=qs1)
.add_yaxis("CO监测值", qs2)
.set_global_opts(title_opts=opts.TitleOpts(title="随时间变化趋势图"))
)
# 图整合
grid_chart = (
Grid()
# .add(line, grid_opts=opts.GridOpts(pos_left="1000", pos_right="100", pos_top="5", pos_bottom="500"))
.add(bar, grid_opts=opts.GridOpts(pos_left="10", pos_right="45%", pos_top="70%", pos_bottom="5"))
.add(map_chart, grid_opts=opts.GridOpts(pos_left="10", pos_right="10", pos_top="5%", pos_bottom="70"))
.add(pie, grid_opts=opts.GridOpts(pos_left="10", pos_right="45%", pos_top="70%", pos_bottom="5"))
# .add(map_chart, grid_opts=opts.GridOpts(pos_left="50", pos_right="250", pos_top="5%", pos_bottom="400"))
)
return grid_chart
time_list = list(range(20200301, 20200332)) # 时间需要改
timeline = Timeline(init_opts=opts.InitOpts(width="1648px", height="800px", theme=ThemeType.DARK))
# 开始编制时间轮播图
for y in time_list:
g = get_day_chart(y)
timeline.add(g, time_point=str(y) + "日")
# 时间轮播图配置项设置
timeline.add_schema(
orient="vertical", # 时间轴的类型:垂直
is_auto_play=True, # 是否自动播放
is_inverse=True, # 是否反向放置 timeline,反向则首位颠倒过来
play_interval=5000, # 表示播放的速度(跳动的间隔),单位毫秒(ms)
pos_left="null",
pos_right="5",
pos_top="20",
pos_bottom="20",
width="85", # 时间轴区域的宽度, 影响垂直的时候时间轴的轴标签和轴之间的距离
label_opts=opts.LabelOpts(is_show=True, color="#fff"), # 时间轴的轴标签配置
)
timeline.render('污染物可视化.html')
print("Done!")
运行结束,会在当前文件夹生成一个名为“污染物可视化.html”的网页文件,双击打开网页,呈现下图。
图中主要包含五个部分:
1.地图
2.柱状图
3.饼图
4.图例
5.时间轴
各个控件之间可以相互影响,,比如选定具体某一天,或者选择某个地区,亦或者是通过图例选定污染物指定数值区间。
同样,也可以将测站的左坐标添加到地图中,如下图所示
写在最后,上面整个流程非常简单,就是为了记录一下学到的一些基本可视化tools,和那些高端大气的大屏无法比拟(他们有的用html进行进一步美化,或者有的读入的数据是从服务器或者数据库中获得,实时性好,便于更改和维护),但是基本框架就是这些,作为自己的一个小小兴趣展现吧(也可能时不务正业,哈哈哈哈哈)。
今天心情很郁闷,没办法集中精力看论文,所以就把之前的东西整理一下,估计整个行文比较混乱,敬请谅解。后续会继续学习,可视化,加上数据库。