利用Python进行数据分析——PM2.5浓度分析

【写在开头】自从开始数据分析的学习,看了很多莎爷[作者:邓莎]的文章,深受启发,非常感谢。我也坚信写作是为了更好地总结与分享。

从Kesci上下载了一份数据集——五大城市的PM2.5数值及相关气象数据。https://www.kesci.com/home/dataset/5d562934c143cf002b2347e9
让我们来看看某城市PM2.5大小跟哪些因素有关吧~
本文的目标是:实现全流程数据分析
如果你有兴趣,跟着我的步骤一起练起来吧
首先看一下各字段的涵义:


先理解一下各字段——season:1-春季 2-夏季 3-秋季 4-冬季;cbwd:组合风向,有东南西北等方向信息。
露点百度一番:空气中的水蒸气变为露珠时候的温度叫露点温度。当空气中水汽已达到饱和时,气温与露点温度相同;当水汽未达到饱和时,气温一定高于露点温度。所以露点与气温的差值可以表示空气中的水汽距离饱和的程度。差值等于零,水汽饱和,差值小于零,水汽未饱和。差值越负,水汽不饱和程度越高。猜测水汽饱和空气中的PM2.5会凝结成液体,使得PM2.5浓度下降。

1. 数据导入

首先老一套,导入将要用的模块:

import numpy as np
import pandas as pd
from datetime import datetime, timedelta, date, time
import matplotlib.pyplot as plt
%matplotlib inline
#plt.rcParams['figure.dpi'] = 300
%config InlineBackend.figure_format='svg'
import seaborn as sns

再用read_csv将csv文件导入成DataFrame格式,并使用parse_dates和date_parser参数解析日期:

#导入数据,并将年月日时间解析为datetime,并设为index
#定义解析公式,datetime.strptime将对应字符串转成datetime
dateparse = lambda dates: pd.datetime.strptime(dates, '%Y %m %d %H')
PM_Shanghai = pd.read_csv('./datasets/FiveCitiePMData/ShanghaiPM20100101_20151231.csv', parse_dates = {'date': ['year','month','day','hour']},date_parser=dateparse,index_col = 'date', keep_date_col = True)

2. 数据清洗

拿到一份数据,首先来看一下数据信息:
PM_Shanghai.info()


共有17个字段, No 字段可以删除。
年月日时间都是object类型的,后面要转成int类型的方便使用。
总共有五万多行,PM值有两万多行缺失值。其余字段也有部分缺失值。
再用.head()观察一下前5行:
image.png

2.1 缺失值处理

任何一份数据,先有整体概念之后,一定要对数据进行清洗。对于这种很多的缺失,可以用PM_Shanghai[PM_Shanghai.notnull()]来筛选一下看一下其分布,发现13年之前没有PM的数据。因此针对三个PM缺失值处理如下:

#清洗行列索引
PM_Shanghai.drop('No',axis = 1, inplace = True)
PM_Shanghai = PM_Shanghai.loc['2013':'2015']
#缺失值填充为三个PM的平均值
PM_Shanghai[['PM_Jingan','PM_US Post','PM_Xuhui']] = PM_Shanghai[['PM_Jingan','PM_US Post','PM_Xuhui']].T.fillna(PM_Shanghai[['PM_Jingan','PM_US Post','PM_Xuhui']].T.mean()).T

处理完再show一下缺失值:
PM_Shanghai.isnull().sum().sort_values(ascending = False)

前两个为降水量和降雨量,缺失值接近1/10太多,先不做处理。
观察PM_Shanghai.PRES[PM_Shanghai.PRES.isnull()],得到气压值有2015年7月11号和12号连续两天的数据缺失,因此不好估计,不做填充。 PM_Shanghai.PM_Xuhui[PM_Shanghai.PM_Xuhui.isnull()],为零散分布的,考虑到PM2.5的连续性,用前向填充法 。
PM_Shanghai.TEMP[PM_Shanghai.TEMP.isnull()] PM_Shanghai.HUMI[PM_Shanghai.HUMI.isnull()] PM_Shanghai.DEWP[PM_Shanghai.DEWP.isnull()]
PM_Shanghai.DEWP['2013-3-11'].plot() 观察露点某一日曲线图
温度,湿度,露点温度一般是连续变化的,且缺失值是分散的,用前向填充法填充。 Iws及cbwd风速风向实时变动范围大无法预测,且缺失值很少,不做填充
思路有了,接下来开始操作一番:

#缺失的值用前向填充法
PM_Shanghai[['PM_Jingan','PM_US Post','PM_Xuhui','TEMP','HUMI','DEWP']] = PM_Shanghai[['PM_Jingan','PM_US Post','PM_Xuhui','TEMP','HUMI','DEWP']].fillna(method = 'ffill')

2.2 格式处理及逻辑检查

#年月日小时要转成int类型,否则出图是乱序的
PM_Shanghai.year = PM_Shanghai.year.astype(int)
PM_Shanghai.month = PM_Shanghai.month.astype(int)
PM_Shanghai.day = PM_Shanghai.day.astype(int)
PM_Shanghai.hour = PM_Shanghai.hour.astype(int)
#对数值型数据用describe()函数观察统计值,逻辑都是OK的
PM_Shanghai[['PM_Jingan','PM_US Post','PM_Xuhui','TEMP','HUMI','DEWP','Iws','PRES','Iprec','precipitation']].describe()

2.3 补充待分析字段

考虑到PM2.5跟人类的活动也有关系,我们已有年月日的信息,可以转换成周几的信息以做后续分析。

#使用weekday()方法将日期转成对应的周几
def getweekday(x):
    Week_Day = x.weekday()
    return Week_Day
PM_Shanghai['weekday'] = list(PM_Shanghai.reset_index().date.apply(getweekday))
#或者用下面这条语句
#PM_Shanghai['weekday'] = list(PM_Shanghai.reset_index().date.apply(lambda x : x.weekday()))
#提取是否周末的信息,1为周末,0为工作日
def getweekend(x):
    if x >= 5:
        Weekend = 1
    else:
        Weekend = 0
    return Weekend
PM_Shanghai['weekdend'] = PM_Shanghai['weekday'].apply(getweekend)
#或者用如下三元表达式
#PM_Shanghai['weekend'] = np.where(PM_Shanghai['weekday']>=5,1,0)

露点跟温度之差也添加一下:
PM_Shanghai['diff'] = PM_Shanghai['DEWP']-PM_Shanghai['TEMP']
一通操作完毕,可以进入主题了。

3. 分析什么?

3.1 初识PM2.5

那么问题来了,怎么分析呢。咱们首先看一下PM2.5长什么样。时间趋势如何。

#首先观察三个地点的趋势
fig,axes = plt.subplots(2,1,figsize = (10,8))
PM_Shanghai[['PM_Jingan','PM_US Post','PM_Xuhui']].resample('M').mean().plot(ax = axes[0])
PM_Shanghai.boxplot(column = ['PM_Jingan','PM_US Post','PM_Xuhui'])
axes[1].set_ylim(0,150)

时序图上可以看出PM值有一定的周期性,12月份到1月份左右有峰值,8月份9月份是波谷。



从箱线图和时序图看出来,三地的PM值一致性很高,后续分析可以抽取其中一个地点来分析。

3.2 变量相关性

咱们之前猜测PM2.5浓度跟水汽饱和程度,人类活动,月份,风速风向等有关系,那么我们先用DataFrame的corr()来定量分析一下吧:
PM_Shanghai.corr()


一般相关系数的绝对值在【0.5,1】之间是强相关,【0.2,0.5】之间是有一定相关性,小于0.1或0.05是无相关。但是上面的数据太多了,眼花花,咱们用热地图来直观显示一下吧~

PM_corr = PM_Shanghai.corr()
fig = plt.figure(figsize = (12, 10))
sns.heatmap(PM_corr, annot=True)

PM跟DEWP,温度,风速呈负相关;与压力,季节呈正相关;跟降雨量无明显关联。

4. 分析

4.1离散值对PM的影响

箱线图是对统计对象较完备的分析方式。通过箱线图可以观察数据的分布情况。接下来分析各离散值对PM的影响。
1)PM的箱线图
2)周一到周日PM的箱线图
3)各月份PM的箱线图
4)各季节PM的箱线图
5)周末与否PM的箱线图
6)各小时PM的箱线图
7)各风向PM的箱线图

#设置配色风格为ggplot,图片尺寸,标题字体
plt.style.use('ggplot')
fig = plt.figure(figsize = (12,20))
fig.suptitle('PM_Xuhui Analysis',fontsize = 16, fontweight = 'bold')

#绘制各子图,并设置标签及子标题
ax1 = fig.add_subplot(4,2,1)
sns.boxplot(y = 'PM_Xuhui', data = PM_Shanghai )
ax1.set(ylabel = 'PM2_5',title = 'box plot on PM2_5')

ax2 = fig.add_subplot(4,2,2)
sns.boxplot(x = 'weekday',y = 'PM_Xuhui',data = PM_Shanghai)
ax2.set(ylabel = 'PM2_5', xlabel = 'Weekday', title = 'box plot on PM2_5 across weekday')

ax3 = fig.add_subplot(4,2,3)
sns.boxplot(x = 'month',y = 'PM_Xuhui',data = PM_Shanghai )
ax3.set(ylabel = 'PM2_5', xlabel = 'Month', title = 'box plot on PM2_5 across month')

ax4 = fig.add_subplot(4,2,4)
sns.boxplot(x = 'season',y = 'PM_Xuhui',data = PM_Shanghai)
ax4.set(ylabel = 'PM2_5', xlabel = 'Season', title = 'box plot on PM2_5 across season')

ax5 = fig.add_subplot(4,2,5)
sns.boxplot(x = 'weekend',y = 'PM_Xuhui',data = PM_Shanghai)
ax5.set(ylabel = 'PM2_5', xlabel = 'Weekend', title = 'box plot on PM2_5 across weekend')

ax6 = fig.add_subplot(4,2,6)
sns.boxplot(x = 'hour',y = 'PM_Xuhui',data = PM_Shanghai)
ax6.set(ylabel = 'PM2_5', xlabel = 'Hour', title = 'box plot on PM2_5 across hour')
plt.ylim([0,200])

ax7 = fig.add_subplot(4,2,7)
sns.boxplot(x = 'cbwd',y = 'PM_Xuhui',data = PM_Shanghai)
ax7.set(ylabel = 'PM2_5', xlabel = 'Cbwd', title = 'box plot on PM2_5 across cbwd')


我们看图说话:
1)PM2.5从0到150范围,中位数为50。
2)PM2.5与周几无明显关系
3)PM2.5与月份有关系,11月到1月浓度高,6月份到10月份浓度低
4)PM2.5与季节有关,4冬季最高,其次1春季,夏季秋季浓度低
5)周末与否无明显影响
6)各时段PM2.5浓度有少许差异,早上7,8点与晚上7,8点中位数偏高
7)组合风向对PM2.5浓度有影响,NE和SE方向明显低于SW和NW方向。
总结:PM2.5浓度跟月份季节有关系,猜测是冬季取暖造成污染增加,上海大都市早晚通勤会造成PM2.5略微增加,组合风向的影响很明显,东北风和东南风造成PM2.5浓度下降,上海东边是大海,海风一来瞬间清新。而西边的风刮过来,哎……

4.2连续值对PM2.5的影响

数据集里有温度,湿度,压力,风速,露点温度之差,首先将连续数据分类,再看各分类对PM2.5的影响。

PM_Shanghai['temp_band'] = pd.cut(PM_Shanghai.TEMP,4)
PM_Shanghai['pressure_band'] = pd.cut(PM_Shanghai.PRES,4)
PM_Shanghai['windspeed_band'] = pd.cut(PM_Shanghai.Iws,4)
PM_Shanghai['saturation_band'] = pd.cut(PM_Shanghai['diff'],3)

接下来分析这几个变量在不同季节对PM2.5的影响。

#设置图片尺寸及大标题和字体
fig = plt.figure(figsize = (12,16))
fig.suptitle('PM_Xuhui Bar Analysis',fontsize = 16, fontweight = 'bold')
#第一个子图,各季节温度对PM2.5的影响
ax1 = fig.add_subplot(4,2,1)
sns.barplot(x = 'season', y = 'PM_Xuhui',hue = 'temp_band', data = PM_Shanghai)
#第二个子图,各季节气压对PM2.5的影响
ax2 = fig.add_subplot(4,2,2)
sns.barplot(x = 'season', y = 'PM_Xuhui',hue = 'pressure_band', data = PM_Shanghai)
#第三个子图,各季节水汽饱和程度对PM2.5的影响
ax3 = fig.add_subplot(4,2,3)
sns.barplot(x = 'season', y = 'PM_Xuhui',hue = 'saturation_band', data = PM_Shanghai)
#第四个子图,各风向风速对PM2.5的影响
ax4 = fig.add_subplot(4,2,4)
sns.barplot(x = 'cbwd', y = 'PM_Xuhui',hue = 'windspeed_band', data = PM_Shanghai)
#第五个子图,各风向风速的平均值
ax5 = fig.add_subplot(4,2,5)
sns.barplot(x = 'cbwd', y = 'Iws',data = PM_Shanghai)

看图说话:
1)温度气压与PM2.5不成明显相关性
2)空气中水汽不饱和程度越低(离饱和越近),PM2.5浓度越低。
3)东北风和东南风导致PM2.5浓度降低,风速越大浓度越低
4)风向不定的微风(CV)、西北风和西南风时PM2.5浓度较高,但风速增大时浓度也会降低。同时西北风需要更高的风速才会使得PM2.5浓度降下来。看来西北的污染源不少。
5)各组合风向的平均风速,西北风及东风风速较大
风速风向对PM2.5的影响是非常明显的,下降速度很快;空气中水汽不饱和程度对PM2.5有一定的影响,水汽越趋近饱和,PM2.5浓度越低。

4.3 PM2.5浓度随各月份及各时段的变化趋势

前面看到PM2.5在各月份和各时段的箱线图,接下来通过曲线图来继续分析一下。

fig = plt.figure(figsize = (18,4))
fig.suptitle('PM_Xuhui change with month & hour')

#各月份的PM2.5的平均值
ax1 = fig.add_subplot(1,3,1)
sns.pointplot(x = 'month', y = 'PM_Xuhui',data = PM_Shanghai,ci = None)
#各季节下各时段的PM2.5平均值
ax2 = fig.add_subplot(1,3,2)
sns.pointplot(x = 'hour', y = 'PM_Xuhui',hue = 'season', data = PM_Shanghai,ci = None)
#周末与否各时段的PM2.5平均值
ax3 = fig.add_subplot(1,3,3)
sns.pointplot(x = 'hour', y = 'PM_Xuhui',hue = 'weekend', data = PM_Shanghai, ci = None)
#ci默认为95%置信区间,sd代表数据的标准差(不是均值的标准差)可以看出早上8点附近及晚上8点附近有高峰,通勤导致空气PM2.5增加。周末早高峰不明显

看图说话:
1)各月份的PM2.5浓度平均值差异达到接近70,12月份最高,9月份最低。11,12,1月份三个月浓度最高,7,8,9,10几个月浓度低。这可能跟冬季供暖导致的污染有关
2)各季节下各时段的平均PM2.5浓度,冬季最高,其次春季,夏天秋天浓度浓度较低。同时各季节早8点晚8点附近有波峰。
3)这张图可以明显看出来早8点晚8点附近的波峰。工作日早上8点附近的浓度要高于周末,应该是上班通勤对PM2.5浓度的影响。另外周末夜里1点附近也有个小波峰,猜测周末大家很嗨夜生活比较丰富到凌晨1点回家。下午2点到5点PM2.5是低谷。

5. 总结

PM2.5的浓度跟季节月份相关性很大,可能是冬季供暖的影响,风速风向也会影响,毕竟空气是流通的嘛,警惕西边特别是西北的风,当然风速很大时空气也会变清新,另外出行会使PM2.5浓度增加。空气中水汽的不饱和程度越大,PM2.5浓度也越高,猜测是水汽饱和会使得PM2.5凝结成液体而使其浓度降低。所以干燥的冬季春季PM2.5浓度也会略高。

湿润的夏季刮东北风下午2点到5点该市PM2.5浓度最低。干燥的冬季无风或微微西北风的工作日的早高峰时段该市PM2.5浓度最高。
要改善PM2.5浓度咱也控制不了风速风向,只能人为的多用清洁能源,出行坐公共交通。PS:本文没有考虑工业带来的污染源。

你可能感兴趣的:(利用Python进行数据分析——PM2.5浓度分析)