美文网首页
利用Python进行数据分析——PM2.5浓度分析

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

作者: 升级打怪最欢呀 | 来源:发表于2019-08-25 16:33 被阅读0次

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

    从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浓度分析

          本文链接:https://www.haomeiwen.com/subject/pnrqectx.html