logo资料库

Python数据分析练习:北京、广州PM2.5空气质量分析.pdf

第1页 / 共12页
第2页 / 共12页
第3页 / 共12页
第4页 / 共12页
第5页 / 共12页
第6页 / 共12页
第7页 / 共12页
第8页 / 共12页
资料共12页,剩余部分请下载后查看
Python数据分析练习:北京、广州PM2.5空气质量分析 作者:谢晓峰 http://blog.csdn.net/xiexf189 2017年8月 由于雾霾问题,全社会都很关注空气质量,政府也花了很多钱力图改善空气质量。我们作为城市市民经常要问:我们城市的空气质量到底怎样?这几年我们城市的 空气质量是在改善还是恶化?我们城市的空气质量与其他城市相比,是更好还是更差? 官方媒体一般都是说:我们的空气质量在改善,但有数据证明吗?官方数据可信吗?我们心存疑虑。所以,作为数据狗,还是自己动手吧。 PM2.5是最近几年特别热议的空气质量指标,这要归功于美帝大使馆哦。美国驻华使馆和领馆自己检测PM2.5数据并且在官网发布,这才让国人知道了这个指标,后 来国内官方也开始公布这个指标了。 言归正传,差点忘了,这是一篇Python技术贴。回到这篇文章的主题:用Python做数据分析。我生活在广州,当然以我大广州为分析目标了。 数据源:美国驻华使馆的空气质量检测数据,http://www.stateair.net/web/historical/1/1.html (http://www.stateair.net/web/historical/1/1.html) 包含以下字段: 其中,PM2.5数值所代表的空气质量评价如下表1-1所示:
在此基础上,如果指数大于500,就是大家戏称为“爆表” 问题: 一.广州的空气质量总体如何? 二.广州最近两年的空气质量是否有改善? 三.广州北京两地的空气质量对比 这几个问题其实比较大而空,要落实到具体的指标和维度。从我们掌握的以上数据出发,可以从以下几个指标和维度分析: 1.2016年全年来看,空气质量较好(PM2.5<=100)的天数占比是多少?2015年相比2016年的对比?北京与各自的对比如何? 2.2016年全年来看,空气质量最严重(PM2.5>300)的天数占比是多少?2015年相比2016年的对比?北京与各自的对比如何? 3.2016年全年来看,空气质量与季节(月份)的变化关系是什么? 4.2016年与2015年同时间点对比,空气质量较好和较差的次数分别是多少? 5.2016年广州与北京同时间点对比,空气质量较好和较差的次数分别是多少? 通过以上维度分析,可以基本对前面的三大问题得出大致的判断。当然,有兴趣的童鞋可以根据原始数据出发,从更多的维度进行分析哦。 下面就开始进入数据集吧。 1. 数据集下载、读取和清洗 从美驻华使馆官网下载了广州、北京两个城市,2015年和2016年的PM2.5数据。分别是这四个文件: Beijing_2015_HourlyPM25_created20160201.csv Beijing_2016_HourlyPM25_created20170201.csv Guangzhou_2015_HourlyPM25_created20170201.csv Guangzhou_2016_HourlyPM25_created20170201.csv 为了简化工作,每个文件只保留这几个字段:Year、Month、Day、Hour、Value和QC name,用Excel删掉其他的字段和文字,千万注意要保留表头哦。 经过大致观察,可以发现以下几点: 1. 数据以csv格式保存,每年1个文件 2. 每个小时一条检测数据 首先引入必要的Python包
In [1]: inline % 从csv文件中读入数据 pandas是Python中常用的数据分析工具,包含了大量简便的数据分析处理方法。本文通过这个例子,展现了几个常用的pandas使用方法。 其中,使用pandas可以很方便地从csc文件中读取数据,保存在DataFrame对象中,方法如下: In [2]: df_bj2015 = pd.read_csv('data/Beijing_2015_HourlyPM25_created20160201.csv') df_bj2015.columns=['Year','Month','Day','Hour','Value','QC'] 数据探索和清洗 拿到数据集,并且导入了DataFrame对象后,我们需要对数据进行观察,看看是否有缺失和错误的情况,并且对数据集进行必要的清洗处理,以便后续得到更准确 的分析结果。 In [3]: Out[3]: df_bj2015.head() Year Month Day Hour Value QC Valid 22 1 0 0 2015 1 1 2015 1 2 2015 1 3 2015 1 4 2015 1 1 1 1 1 9 9 13 10 Valid Valid Valid Valid 1 2 3 4 In [4]: df_bj2015.describe() Out[4]: Year Month Day Hour Value 0.0 71.658904 15.720548 11.500114 count 8760.0 8760.000000 8760.000000 8760.000000 8760.000000 mean 2015.0 6.526027 std 3.448048 min 2015.0 1.000000 25% 2015.0 4.000000 50% 2015.0 7.000000 75% 2015.0 10.000000 max 2015.0 12.000000 -999.000000 139.751292 108.000000 722.000000 17.250000 16.000000 11.500000 31.000000 23.000000 8.796749 1.000000 8.000000 21.000000 6.922433 0.000000 5.750000 53.000000 23.000000 从简要描述中,可以看出Value字段(pm2.5的值)最小值是-999,正常来说,PM2.5的值不会小于零的,这说明有些观测值是缺失或者记录错误。我们可以计算一 下其中有多少Value<0的记录: In [5]: len(df_bj2015.ix[df_bj2015.Value<0, :]) Out[5]: 97 全年8000多条数据中,只有97条记录缺失或错误,所以把这97条记录删除,对整个分析影响不大。以下把缺失或错误的记录删除: In [6]: df_bj2015.loc[df_bj2015.Value<0,'Value']=np.nan df_bj2015.dropna(inplace=True) 再用describe方法看看数据集的概况: i m p o r t u n i c o d e c s v i m p o r t p a n d a s a s p d i m p o r t n u m p y a s n p i m p o r t m a t p l o t l i b . p y p l o t a s p l t i m p o r t s e a b o r n a s s b m a t p l o t l i b # 从 c s v 中 读 取 北 京 2 0 1 5 年 p m 2 . 5 数 据 , 保 存 在 D a t a F r a m e 中 # 重 新 设 定 各 个 字 段 的 名 称 # 查 看 D a t a F r a m e 中 的 前 几 条 数 据 # D a t a F r a m e 的 简 要 描 述 # 把 错 误 值 置 为 空 值 # 删 除 空 值 记 录
In [7]: df_bj2015.describe() Out[7]: Year Month Day Hour Value 0.0 8.787195 11.494055 82.733810 15.674939 count 8663.0 8663.000000 8663.000000 8663.000000 8663.000000 mean 2015.0 6.538728 std 3.448080 min 2015.0 1.000000 25% 2015.0 4.000000 50% 2015.0 7.000000 75% 2015.0 10.000000 max 2015.0 12.000000 109.000000 722.000000 88.556186 18.000000 23.000000 21.000000 16.000000 54.000000 23.000000 31.000000 11.000000 6.938605 0.000000 1.000000 0.000000 5.000000 8.000000 可以看出,Value字段最小值不再为负数,这样的数据基本可信。 另外,我们还要为数据集增加一个字段,根据前面表1-1的划分方法,把pm2.5的测量值Value,转换为空气质量等级。 首先,我们先写一个函数,通过pm2.5测量值 对应的空气质量等级。 In [8]: df_bj2015.describe() Out[8]: Year Month Day Hour Value 0.0 8.787195 11.494055 82.733810 15.674939 count 8663.0 8663.000000 8663.000000 8663.000000 8663.000000 mean 2015.0 6.538728 std 3.448080 min 2015.0 1.000000 25% 2015.0 4.000000 50% 2015.0 7.000000 75% 2015.0 10.000000 max 2015.0 12.000000 109.000000 722.000000 18.000000 23.000000 88.556186 21.000000 16.000000 54.000000 23.000000 31.000000 11.000000 6.938605 0.000000 5.000000 1.000000 0.000000 8.000000 In [9]: get_grade(value): value <= 50 value>=0: 'Good' value <= 100: 'Moderate' value <= 150: 'Unhealthy for Sensi' value <= 200: 'Unhealthy' value <= 300: 'Very Unhealthy' value <= 500: 'Hazardous' value > 500: 'Beyond Index' : None 以下使用DataFrame的apply函数,增加一个字段‘Grade’,并且根据‘Value’字段的值,调用前面的转换函数,为‘Grade’字段赋值。 In [10]: df_bj2015.loc[:, 'Grade'] = df_bj2015['Value'].apply(get_grade) 再来看看增加字段后的数据集 In [11]: df_bj2015.head() Out[11]: Year Month Day Hour Value QC Grade Valid Good 22.0 1 0 0 2015 1 1 2015 1 2 2015 1 3 2015 1 4 2015 1 1 1 1 1 1 2 3 4 9.0 9.0 13.0 10.0 Valid Good Valid Good Valid Good Valid Good d e f i f a n d r e t u r n e l i f r e t u r n e l i f r e t u r n e l i f r e t u r n e l i f r e t u r n e l i f r e t u r n e l i f r e t u r n # 爆 表 了 e l s e r e t u r n # 输 入 值 无 效
经过以上的处理,我们就把北京2015年的PM2.5数据集处理完成了。对于其他三个表格,我们都采取类似的处理。 In [12]: df_bj2016 = pd.read_csv('data/Beijing_2016_HourlyPM25_created20170201.csv') df_bj2016.columns=['Year','Month','Day','Hour','Value','QC'] df_bj2016.loc[df_bj2016.Value<0,'Value']=np.nan df_bj2016.dropna(inplace=True) df_bj2016.loc[:, 'Grade'] = df_bj2016['Value'].apply(get_grade) In [13]: df_bj2016.head() Out[13]: Year Month Day Hour Value QC Grade 0 2016 1 1 2016 1 2 2016 1 3 2016 1 4 2016 1 1 1 1 1 1 0 1 2 3 4 231.0 Valid Very Unhealthy 239.0 Valid Very Unhealthy 205.0 Valid Very Unhealthy 167.0 Valid Unhealthy 132.0 Valid Unhealthy for Sensi In [14]: df_gz2016 = pd.read_csv('data/Guangzhou_2016_HourlyPM25_created20170201.csv') df_gz2016.columns=['Year','Month','Day','Hour','Value','QC'] df_gz2016.loc[df_gz2016.Value<0,'Value']=np.nan df_gz2016.dropna(inplace=True) df_gz2016.loc[:, 'Grade'] = df_gz2016['Value'].apply(get_grade) In [15]: df_gz2016.head() Out[15]: Year Month Day Hour Value QC Grade 0 2016 1 1 2016 1 2 2016 1 3 2016 1 4 2016 1 1 1 1 1 1 0 1 2 3 4 55.0 58.0 59.0 58.0 51.0 Valid Moderate Valid Moderate Valid Moderate Valid Moderate Valid Moderate In [16]: df_gz2015 = pd.read_csv('data/Guangzhou_2015_HourlyPM25_created20160201.csv') df_gz2015.columns=['Year','Month','Day','Hour','Value','QC'] df_gz2015.loc[df_gz2015.Value<0,'Value']=np.nan df_gz2015.dropna(inplace=True) df_gz2015.loc[:, 'Grade'] = df_gz2015['Value'].apply(get_grade) # 从 c s v 中 读 取 北 京 2 0 1 6 年 p m 2 . 5 数 据 , 保 存 在 D a t a F r a m e 中 # 重 新 设 定 各 个 字 段 的 名 称 # 对 错 误 和 缺 失 值 赋 为 空 值 # 删 除 空 值 记 录 # 增 加 空 气 质 量 等 级 字 段 ‘ G r a d e ’ # 从 c s v 中 读 取 广 州 2 0 1 6 年 p m 2 . 5 数 据 , 保 存 在 D a t a F r a m e 中 # 重 新 设 定 各 个 字 段 的 名 称 # 对 错 误 和 缺 失 值 赋 为 空 值 # 删 除 空 值 记 录 # 增 加 空 气 质 量 等 级 字 段 ‘ G r a d e ’ # 从 c s v 中 读 取 广 州 2 0 1 5 年 p m 2 . 5 数 据 , 保 存 在 D a t a F r a m e 中 # 重 新 设 定 各 个 字 段 的 名 称 # 对 错 误 和 缺 失 值 赋 为 空 值 # 删 除 空 值 记 录 # 增 加 空 气 质 量 等 级 字 段 ‘ G r a d e ’
In [17]: df_gz2015.head() Out[17]: Year Month Day Hour Value QC Grade Valid Good 38.0 1 0 0 2015 1 1 2015 1 2 2015 1 3 2015 1 4 2015 1 1 1 1 1 1 2 3 4 40.0 40.0 34.0 42.0 Valid Good Valid Good Valid Good Valid Good 好了,我们已经把本次分析所需的数据集全部准备完毕,接下来就是进行数据的分析 2. 数据分析 2.1 空气质量等级的对比分析 广州2015年与2016年的空气质量等级对比,分别统计全年各个等级的次数占比(例如:Good占比 = Good次数/全年总测量次数) In [18]: gz2015_grade = df_gz2015.groupby(['Grade']).size()/len(df_gz2015) In [19]: gz2016_grade = df_gz2016.groupby(['Grade']).size()/len(df_gz2016) In [20]: bj2015_grade = df_bj2015.groupby(['Grade']).size()/len(df_bj2015) In [21]: bj2016_grade = df_bj2016.groupby(['Grade']).size()/len(df_bj2016) 为了更方便地进行对比,我们把两地两年的等级数据放到同一个DataFrame中: In [22]: ix_grade = ['Good', 'Moderate', 'Unhealthy for Sensi', 'Unhealthy', 'Very Unhealthy', 'Hazardous','Beyond Index'] In [23]: In [24]: df_grade = pd.DataFrame(gz2015_grade, index = ix_grade, columns=['gz2015']) df_grade['gz2016'] = gz2016_grade df_grade['bj2015'] = bj2015_grade df_grade['bj2016'] = bj2016_grade In [25]: Out[25]: df_grade gz2016 gz2015 0.746356 0.820680 0.476625 0.507838 bj2015 bj2016 Good Moderate 0.208163 0.162640 0.245989 0.259297 Unhealthy for Sensi 0.036851 0.012756 0.119820 0.107335 Unhealthy 0.007580 0.002698 0.059333 0.054926 Very Unhealthy Hazardous Beyond Index 0.001050 0.001227 0.063719 0.048060 0.029436 0.020483 0.005079 0.002060 NaN NaN NaN NaN # 定 义 一 个 空 气 质 量 等 级 索 引 # 创 建 一 个 D a t a F r a m e 对 象 , 先 把 广 州 2 0 1 5 年 的 空 气 质 量 等 级 占 比 数 据 加 进 去 # 接 下 来 把 其 他 三 个 等 级 数 据 也 加 进 D a t a F r a m e 中 # 查 看 我 们 获 得 的 D a t a F r a m e , 这 里 包 含 了 两 地 两 年 的 空 气 质 量 等 级 占 比 数 据
In [26]: df_grade.ix[:,'gz2016'].plot.pie(title = 'Guangzhou 2016 AQI' ,autopct = ' ', fontsize = 12, figsize=(6,6)) Out[26]: 为了更直观地进行对比,我们可以画出对比柱状图,分别包括:广州2015年和2016年对比、北京和广州2016年对比、北京2015年和2016年对比。 In [27]: df_grade.ix[:,['gz2015','gz2016']].plot.bar(title='Guangzhou AQI 2015 vs 2016', figsize=(8,6),fontsize = 12 ) Out[27]: # 使 用 饼 图 查 看 广 州 2 0 1 6 年 空 气 质 量 等 级 占 比 % . 1 f % %
In [28]: df_grade.ix[:,['gz2016','bj2016']].plot.bar(title='2016 AQI Guangzhou vs Beijing', figsize=(8,6),fontsize = 12) Out[28]: In [29]: df_grade.ix[:,['bj2015','bj2016']].plot.bar(title='Beijing AQI 2015 vs 2016', figsize=(8,6),fontsize = 12) Out[29]: 从图表可以明显看出以下结论: 1. 本地的不同年份对比,北京和广州的情况类似,本地2016年相比2015年,空气质量测量值良好和中等的占比提升了,不健康的占比下降了。可以说广州和 北京的空气质量在好转。 2. 广州和北京的同一年份对比,广州空气良好的比重比北京高,空气不健康的比重比北京低得多。在空气质量方面,广州人民比北京人民要幸福啊。 2.2 月度趋势和对比分析 接下来,我们从全年情况来看,分析空气质量随季节(月份)的变化趋势,以及两地的对比分析。 首先计算出两地两年的每月平均测量值: In [30]: gz2015_month = df_gz2015.groupby(['Month'])['Value'].mean() gz2016_month = df_gz2016.groupby(['Month'])['Value'].mean() bj2015_month = df_bj2015.groupby(['Month'])['Value'].mean() bj2016_month = df_bj2016.groupby(['Month'])['Value'].mean() # 计 算 两 地 两 年 的 p m 2 . 5 测 量 值 月 度 平 均 值
分享到:
收藏