操作系统:Linux/Windows10
开发工具: Jupyter Notebook
编程环境 :Python 3.8,Pandas 1.1.x,Matplotlib 3.3.x(建议安装Anaconda3环境)
盛华化工锅炉排放数据,数据包含两个锅炉烟气脱硫出口排放氮氧化物、 二氧化硫和烟尘的检测值,数据时间范围为:2018-11-17 23:00:00
- 2018-11-27 23:00:00
。
通过可视化数据分析,发现排放异常情况,并结合实际情况进行相应整顿。
数据导入
实验数据为excel文件(相应数据文件及源代码可在文末的链接中下载),可以使用pandas的read_excel进行导入。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#数据导入
#sheet_name指定要读取的sheet,可以是代表顺序的整数、sheet的名称,或者是它们组成的列表,默认为None,将读取所有sheet
#header, 指定数据的字段信息所在的行,可以是整数或者是整数组成的列表,如果设为None,表示数据中没有字段信息。
data = pd.read_excel("盛华化工锅炉排放数据.xlsx",sheet_name=0,header=1)
观察数据
(1) 查看数据的前五行数据
data.head(5)
通过观察,数据文件被正确解析,数据为典型的长格式,在数据分析之前需要进行数据重塑,将长格式转换成宽格式。
(2) 观察数据概况,包括数据的行索引,列索引,数据类型,非空值个数以及内存使用情况
data.info()
数据包含1411条样本,通过观察发现数据没有缺失值,并且数据时间列正确解析为datetime64[ns]类型。
(3) 观察数据的统计信息
data.describe()
(4) 观察有哪些排放口和排放指标
data['排放口'].drop_duplicates(), data['指标名称'].drop_duplicates()
排放口一共有两个,分别为1号锅炉和2号锅炉,一共包含三个排放指标,分别为:氮氧化物、 二氧化硫、烟尘
希望分析各类排放指标在不同时间点(以小时为单位)的平均观测值,所以需要根据数据时间生成小时列。
#生成时间_小时列
data["时间_小时"] = data["数据时间"].apply(lambda x : x.hour)
data.head()
输出结果为:
数据时间 | 排放口 | 指标名称 | 检测值 | 排放标准 | 是否超标 | 时间_小时 | |
---|---|---|---|---|---|---|---|
0 | 2018-11-27 23:00:00 | 2号锅炉烟气脱硫出口 | 氮氧化物 | 82.52 | 100 | 否 | 23 |
1 | 2018-11-27 23:00:00 | 2号锅炉烟气脱硫出口 | 二氧化硫 | 0.25 | 35 | 否 | 23 |
2 | 2018-11-27 23:00:00 | 1号锅炉烟气脱硫出口 | 氮氧化物 | 59.64 | 100 | 否 | 23 |
3 | 2018-11-27 23:00:00 | 1号锅炉烟气脱硫出口 | 烟尘 | 2.24 | 10 | 否 | 23 |
4 | 2018-11-27 23:00:00 | 2号锅炉烟气脱硫出口 | 烟尘 | 2.33 | 10 | 否 | 23 |
将长格式转换为宽格式,注意这里的数据维度包括:时间_小时、指标名称、排放口;数据值包括:检测值和排放标准。
首先通过pivot_table方法生成检测数据的宽格式
#数据重塑
#index指定行索引使用的列,如果指定多个列为行索引,则生成多级索引
#columns指定列索引将要使用的列,如果指定多个列为列索引,则生成多级索引
#values指定透视图观察的数据
#aggfunc指定如果聚合观察值
indicators = pd.pivot_table(data,
index='时间_小时',
columns = ['指标名称','排放口'],
values = '检测值',
aggfunc='mean')
indicators
输出结果为:
指标名称 | 二氧化硫 | 氮氧化物 | 烟尘 | |||
---|---|---|---|---|---|---|
排放口 | 1号锅炉烟气脱硫出口 | 2号锅炉烟气脱硫出口 | 1号锅炉烟气脱硫出口 | 2号锅炉烟气脱硫出口 | 1号锅炉烟气脱硫出口 | 2号锅炉烟气脱硫出口 |
时间_小时 | ||||||
0 | 2.861429 | 1.002727 | 74.640000 | 124.220909 | 2.355455 | 2.619091 |
1 | 4.484286 | 0.416667 | 72.610000 | 126.891818 | 2.386364 | 2.568182 |
2 | 5.078333 | 0.793333 | 72.085455 | 132.177273 | 2.460000 | 2.694545 |
3 | 2.958333 | 1.055714 | 70.493636 | 147.014545 | 2.532727 | 2.764545 |
4 | 2.485714 | 0.788571 | 71.782727 | 151.588182 | 2.346364 | 2.813636 |
5 | 2.712500 | 0.448000 | 68.623333 | 142.042727 | 2.338333 | 2.751000 |
6 | 2.683333 | 0.560000 | 72.127273 | 141.451818 | 2.473636 | 2.742727 |
7 | 2.526250 | 0.468571 | 69.035455 | 135.746364 | 2.434545 | 2.591818 |
8 | 3.065714 | 3.040000 | 69.292727 | 134.071818 | 2.421818 | 2.640000 |
9 | 3.162500 | 1.761000 | 69.881818 | 109.648182 | 2.615455 | 2.511818 |
10 | 2.331111 | 0.983750 | 70.605000 | 118.843000 | 2.640000 | 2.409167 |
11 | 3.545714 | 0.685714 | 71.384545 | 119.827273 | 2.793636 | 2.545455 |
12 | 4.290000 | 0.818000 | 65.349091 | 119.972727 | 11.012727 | 2.558182 |
13 | 2.085556 | 1.037778 | 69.407273 | 115.346364 | 2.641818 | 2.450000 |
14 | 1.842000 | 1.295455 | 70.449091 | 105.007273 | 2.565455 | 2.519091 |
15 | 4.302222 | 1.604444 | 70.928333 | 122.390000 | 3.660909 | 2.608000 |
16 | 4.566364 | 1.182727 | 72.358182 | 104.283333 | 5.447000 | 2.453636 |
17 | 3.441429 | 0.640000 | 73.279091 | 82.249091 | 2.665455 | 2.348182 |
18 | 1.394444 | 0.347143 | 71.234545 | 112.404545 | 2.521818 | 2.509091 |
19 | 5.027143 | 0.623333 | 71.381818 | 126.155455 | 2.443636 | 2.569091 |
20 | 2.657500 | 0.245714 | 68.595455 | 123.407273 | 2.474545 | 2.659091 |
21 | 2.187143 | 1.098889 | 67.420909 | 123.883636 | 2.614000 | 2.623636 |
22 | 0.903333 | 0.600000 | 70.330909 | 124.541818 | 2.480909 | 2.549091 |
23 | 9.514000 | 0.668750 | 75.206364 | 124.250909 | 2.401818 | 2.624545 |
提取排放标准的数据,该数据只涉及指标名称一个维度
standard = data[['指标名称','排放标准']].drop_duplicates().set_index('指标名称')
standard
输出结果为:
排放标准 | |
---|---|
指标名称 | |
氮氧化物 | 100 |
二氧化硫 | 35 |
烟尘 | 10 |
准备工作
将使用pandas和matplotlib完成数据可视化分析,通过如下设置解决中文显示问题,并设置画布大小
# 用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']
# 用来正常显示负号
plt.rcParams['axes.unicode_minus'] = False
# 设置画布大小
plt.rcParams['figure.figsize'] = (8,5)
#设置dpi
plt.rcParams['figure.dpi'] = 120
对两个排放口在各个时间点的检测值与排放标准进行对比分析
#定义绘图函数,对比分析各个时间点上的检测值与排放标准的差距
def plot_indicator_hours(indicator):
indicators[indicator].plot(title=F'{indicator}各个时间点的排放情况')
#绘制排放标准的参考线
plt.axhline(y=standard['排放标准'][indicator], c='g',ls='--')
(1) 氮氧化物在各个时间点上的排放情况
#可视化氮氧化物在各个时间点上的排放情况
plot_indicator_hours('氮氧化物')
分析结果:绿色虚线为氮氧化物的排放标准,1号锅炉烟气脱硫出口的氮氧化物排放量达标,排放量比较平稳;2号锅炉烟气脱硫出口的氮氧化物排放量超标,排放量波动较大。
(2) 二氧化硫在各个时间点上的排放情况
plot_indicator_hours('二氧化硫')
分析结果:绿色虚线为二氧化硫的排放标准,两个排放口的排放情况良好,其中1号锅炉烟气脱硫出口的二氧化硫排放略高于2号锅炉。
(3) 烟尘在各个时间点上的排放情况
plot_indicator_hours('烟尘')
分析结果:绿色虚线为烟尘的排放标准,其中2号锅炉烟气脱硫出口的烟尘排放量良好,排放情况稳定;1号锅炉烟气脱硫出口的烟尘排放量在中午12点和下午4点时排放量异常偏高,且中午12点的排放量超标,可结合实际情况考虑测量数据是否异常或者其他原因引起的排放量增高。
对两个排放口各个排放指标与排放标准进行对比分析
#计算各个指标的检测值平均值
mean_indicator = indicators.mean().to_frame().unstack().droplevel(0,axis=1)
#计算各个指标与排放标准的差值
diff_indicator = pd.concat([mean_indicator,standard],axis=1)
diff_indicator['1号锅炉排放指标'] = diff_indicator['1号锅炉烟气脱硫出口']-diff_indicator['排放标准']
diff_indicator['2号锅炉排放指标'] = diff_indicator['2号锅炉烟气脱硫出口']-diff_indicator['排放标准']
#绘制柱状图
diff_indicator[['1号锅炉排放指标','2号锅炉排放指标']].plot.bar()
分析结果:
二氧化硫:两个排放口均达标,其中2号锅炉排放更平稳,排放量更低。
氮氧化物:1号锅炉排放达标,且排放量平稳;2号锅炉排放超标,且排放量波动较大,需要整顿。
烟尘:2号锅炉排放达标,且排放量平稳;1号锅炉排放量基本达标,但排放波动大,且在中午12时的检测测超标,需要排查原因。
链接:https://pan.baidu.com/s/1b9z18GSmUqwUuimZt_lHsQ?pwd=k90y
提取码:k90y