Python数据分析练习:北京、广州PM2.5空气质量分析(2)
<接上一篇>
2. 数据分析
2.1 空气质量等级的对比分析
广州2015年与2016年的空气质量等级对比,分别统计全年各个等级的次数占比(例如:Good占比 = Good次数/全年总测量次数)
gz2015_grade = df_gz2015.groupby(['Grade']).size()/len(df_gz2015)
gz2016_grade = df_gz2016.groupby(['Grade']).size()/len(df_gz2016)
bj2015_grade = df_bj2015.groupby(['Grade']).size()/len(df_bj2015)
bj2016_grade = df_bj2016.groupby(['Grade']).size()/len(df_bj2016)
为了更方便地进行对比,我们把两地两年的等级数据放到同一个DataFrame中:
# 定义一个空气质量等级索引 ix_grade = ['Good', 'Moderate', 'Unhealthy for Sensi', 'Unhealthy', 'Very Unhealthy', 'Hazardous','Beyond Index']
# 创建一个DataFrame对象,先把广州2015年的空气质量等级占比数据加进去 df_grade = pd.DataFrame(gz2015_grade, index = ix_grade, columns=['gz2015'])
# 接下来把其他三个等级数据也加进DataFrame中 df_grade['gz2016'] = gz2016_grade df_grade['bj2015'] = bj2015_grade df_grade['bj2016'] = bj2016_grade
# 查看我们获得的DataFrame,这里包含了两地两年的空气质量等级占比数据 df_grade
gz2015 | gz2016 | bj2015 | bj2016 | |
---|---|---|---|---|
Good | 0.746356 | 0.820680 | 0.476625 | 0.507838 |
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 | 0.001050 | 0.001227 | 0.063719 | 0.048060 |
Hazardous | NaN | NaN | 0.029436 | 0.020483 |
Beyond Index | NaN | NaN | 0.005079 | 0.002060 |
# 使用饼图查看广州2016年空气质量等级占比 df_grade.ix[:,'gz2016'].plot.pie(title = 'Guangzhou 2016 AQI' ,autopct = '%.1f%%', fontsize = 12, figsize=(6,6))
<matplotlib.axes._subplots.AxesSubplot at 0xb8e52b0>
为了更直观地进行对比,我们可以画出对比柱状图,分别包括:广州2015年和2016年对比、北京和广州2016年对比、北京2015年和2016年对比。
df_grade.ix[:,['gz2015','gz2016']].plot.bar(title='Guangzhou AQI 2015 vs 2016', figsize=(8,6),fontsize = 12 )
<matplotlib.axes._subplots.AxesSubplot at 0xbd24e80>
df_grade.ix[:,['gz2016','bj2016']].plot.bar(title='2016 AQI Guangzhou vs Beijing', figsize=(8,6),fontsize = 12)
<matplotlib.axes._subplots.AxesSubplot at 0xbe45048>
df_grade.ix[:,['bj2015','bj2016']].plot.bar(title='Beijing AQI 2015 vs 2016', figsize=(8,6),fontsize = 12)
<matplotlib.axes._subplots.AxesSubplot at 0xc2f13c8>
从图表可以明显看出以下结论:
本地的不同年份对比,北京和广州的情况类似,本地2016年相比2015年,空气质量测量值良好和中等的占比提升了,不健康的占比下降了。可以说广州和北京的空气质量在好转。
广州和北京的同一年份对比,广州空气良好的比重比北京高,空气不健康的比重比北京低得多。在空气质量方面,广州人民比北京人民要幸福啊。
2.2 月度趋势和对比分析
接下来,我们从全年情况来看,分析空气质量随季节(月份)的变化趋势,以及两地的对比分析。
首先计算出两地两年的每月平均测量值:
# 计算两地两年的pm2.5测量值月度平均值 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()
为了方便对比,把上述平均值放到同一个DataFrame中。
df_month = pd.DataFrame({'gz2015':gz2015_month}, index = np.arange(1,13))
df_month['gz2016'] = gz2016_month df_month['bj2015'] = bj2015_month df_month['bj2016'] = bj2016_month
df_month
gz2015 | gz2016 | bj2015 | bj2016 | |
---|---|---|---|---|
1 | 70.210306 | 35.413352 | 107.914750 | 72.146703 |
2 | 67.240487 | 37.168622 | 96.737237 | 43.959538 |
3 | 41.238806 | 50.401372 | 89.274895 | 93.125168 |
4 | 39.898470 | 40.774242 | 78.855134 | 66.500000 |
5 | 29.328804 | 27.272340 | 60.128378 | 55.245614 |
6 | 17.942976 | 22.398148 | 54.397436 | 59.008427 |
7 | 23.121253 | 20.051034 | 55.083558 | 60.075239 |
8 | 31.863329 | 30.260606 | 44.647376 | 38.727395 |
9 | 37.368124 | 22.630048 | 47.089261 | 51.595833 |
10 | 42.043069 | 22.668975 | 72.812500 | 82.092266 |
11 | 38.402244 | 38.969144 | 124.822222 | 104.739191 |
12 | 38.302703 | 48.918033 | 161.956403 | 144.628032 |
df_month.ix[:, ['gz2015','gz2016']].plot(title='Guangzhou PM2.5 Monthly Avg. 2015 vs 2016', figsize=(8,4))
<matplotlib.axes._subplots.AxesSubplot at 0xc39f0f0>
从以上折线图可以看出,广州地区春冬季空气质量较差,夏秋季空质量较好。2016年的大部分月份平均PM2.5值比2015年同期较低,只有3月和12月比2015年同期较高。
df_month.ix[:, ['bj2015','bj2016']].plot(title='Beijing PM2.5 Monthly Avg. 2015 vs 2016', figsize=(8,4))
<matplotlib.axes._subplots.AxesSubplot at 0xcc4b160>
从以上折线图可以看出,北京地区全年的PM2.5值基本呈U字形,冬季空气质量特别差,春季较差,夏秋季空质量较好。2016年大部分月份平均PM2.5值与2015年同期基本持平,只1、2月比2015年同期有较大幅度下降。
df_month.ix[:, ['gz2016','bj2016']].plot(title='2016 PM2.5 Monthly Avg. Beijing vs Guangzhou', figsize=(8,4))
<matplotlib.axes._subplots.AxesSubplot at 0xcef2e80>
从以上折线图可以看出,2016年广州全年各月份的PM2.5平均值都比北京低,其中12月的均值只有北京同期的三分之一。
2.3 每小时测量值对比分析
前面的对比分析,都不是直接把测量数据进行对比,而是进行了平均或分级处理,这样的处理虽然也能看出总体趋势,但是毕竟损失了一些信息。接下来,我们不再对数据进行变换处理,而是直接把每个按小时测量的数据进行一一对比,计算出大于、等于和小于的次数。
为了方便操作,我们把两地两年的四个DataFrame合并在一起,行索引为('Month', 'Day', 'Hour'),列索引为('gz2015','gz2016','bj2015','bj2016')。
以下是合并重新生成一个DataFrame的过程。
df_hour = pd.DataFrame({'Month': df_gz2015.ix[:,'Month'], 'Day' : df_gz2015.ix[:,'Day'],'Hour' : df_gz2015.ix[:,'Hour'],'gz2015':df_gz2015.ix[:,'Value']})
df_hour.describe()
Day | Hour | Month | gz2015 | |
---|---|---|---|---|
count | 8575.000000 | 8575.000000 | 8575.000000 | 8575.000000 |
mean | 15.576676 | 11.507172 | 6.497726 | 39.499942 |
std | 8.752709 | 6.931227 | 3.428460 | 29.009505 |
min | 1.000000 | 0.000000 | 1.000000 | 1.000000 |
25% | 8.000000 | 5.000000 | 4.000000 | 19.000000 |
50% | 16.000000 | 12.000000 | 7.000000 | 32.000000 |
75% | 23.000000 | 18.000000 | 9.000000 | 51.000000 |
max | 31.000000 | 23.000000 | 12.000000 | 259.000000 |
下面先把广州2016年的数据合并进去
df_hour = df_hour.merge(df_gz2016.ix[:,['Month','Day','Hour','Value']], on=('Month','Day','Hour'))
df_hour.rename_axis({'Value':'gz2016'}, axis="columns", inplace=True)
df_hour.describe()
Day | Hour | Month | gz2015 | gz2016 | |
---|---|---|---|---|---|
count | 7957.000000 | 7957.000000 | 7957.000000 | 7957.000000 | 7957.000000 |
mean | 15.564032 | 11.541033 | 6.556994 | 39.967827 | 33.130325 |
std | 8.808309 | 6.935092 | 3.463692 | 29.553651 | 24.323558 |
min | 1.000000 | 0.000000 | 1.000000 | 1.000000 | 0.000000 |
25% | 8.000000 | 6.000000 | 4.000000 | 19.000000 | 16.000000 |
50% | 15.000000 | 12.000000 | 7.000000 | 33.000000 | 28.000000 |
75% | 23.000000 | 18.000000 | 10.000000 | 51.000000 | 44.000000 |
max | 31.000000 | 23.000000 | 12.000000 | 259.000000 | 266.000000 |
合并主要使用了merge方法,可以确保合并时在月、日、时三个索引上一一对应,对应不上(例如某个时间有测量数据缺失),则只保留交集部分,其他的丢弃。从合并前后的DataFrame描述来看,记录数有减少,这是因为有些未交集的记录丢弃了。
下面用同样的方法,把北京2015和2016年的数据合并进去。
df_hour = df_hour.merge(df_bj2015.ix[:,['Month','Day','Hour','Value']], on=('Month','Day','Hour')) df_hour.rename_axis({'Value':'bj2015'}, axis="columns", inplace=True)df_hour = df_hour.merge(df_bj2016.ix[:,['Month','Day','Hour','Value']], on=('Month','Day','Hour')) df_hour.rename_axis({'Value':'bj2016'}, axis="columns", inplace=True)
df_hour.head()
Day | Hour | Month | gz2015 | gz2016 | bj2015 | bj2016 | |
---|---|---|---|---|---|---|---|
0 | 1 | 0 | 1 | 38.0 | 55.0 | 22.0 | 231.0 |
1 | 1 | 1 | 1 | 40.0 | 58.0 | 9.0 | 239.0 |
2 | 1 | 2 | 1 | 40.0 | 59.0 | 9.0 | 205.0 |
3 | 1 | 3 | 1 | 34.0 | 58.0 | 13.0 | 167.0 |
4 | 1 | 4 | 1 | 42.0 | 51.0 | 10.0 | 132.0 |
df_hour.describe()
Day | Hour | Month | gz2015 | gz2016 | bj2015 | bj2016 | |
---|---|---|---|---|---|---|---|
count | 7833.000000 | 7833.000000 | 7833.000000 | 7833.000000 | 7833.000000 | 7833.000000 | 7833.000000 |
mean | 15.493681 | 11.534661 | 6.567471 | 39.947530 | 33.131750 | 81.893527 | 70.324269 |
std | 8.805105 | 6.954496 | 3.465844 | 29.546365 | 24.352084 | 87.343633 | 75.638957 |
min | 1.000000 | 0.000000 | 1.000000 | 1.000000 | 0.000000 | 0.000000 | 0.000000 |
25% | 8.000000 | 6.000000 | 4.000000 | 19.000000 | 16.000000 | 22.000000 | 17.000000 |
50% | 15.000000 | 12.000000 | 7.000000 | 33.000000 | 28.000000 | 55.000000 | 47.000000 |
75% | 23.000000 | 18.000000 | 10.000000 | 51.000000 | 44.000000 | 108.000000 | 92.000000 |
max | 31.000000 | 23.000000 | 12.000000 | 259.000000 | 266.000000 | 722.000000 | 782.000000 |
df_hour.head()
Day | Hour | Month | gz2015 | gz2016 | bj2015 | bj2016 | |
---|---|---|---|---|---|---|---|
0 | 1 | 0 | 1 | 38.0 | 55.0 | 22.0 | 231.0 |
1 | 1 | 1 | 1 | 40.0 | 58.0 | 9.0 | 239.0 |
2 | 1 | 2 | 1 | 40.0 | 59.0 | 9.0 | 205.0 |
3 | 1 | 3 | 1 | 34.0 | 58.0 | 13.0 | 167.0 |
4 | 1 | 4 | 1 | 42.0 | 51.0 | 10.0 | 132.0 |
下面进行逐个对比。
len(df_hour[df_hour['gz2015']>df_hour['gz2016']]), 1.0*len(df_hour[df_hour['gz2015']>df_hour['gz2016']])/len(df_hour)
(4366, 0.5573854206561981)
len(df_hour[df_hour['gz2015']<df_hour['gz2016']]),1.0*len(df_hour[df_hour['gz2015']<df_hour['gz2016']])/len(df_hour)
(3342, 0.4266564534661049)
从上述结果中看出,
广州地区2016年有4366次PM2.5测量值比2015年同期小,占比55.7%,
有3342次比2015年同期大,占比42.7%。
可以从总体上来说,2016年的空气质量比2015年好。
也可以画出曲线图进行更直观的对比。
df_hour.ix[:, ['gz2015','gz2016']].plot(title='Guangzhou PM2.5 Hourly 2015 vs 2016', figsize=(12,4))
<matplotlib.axes._subplots.AxesSubplot at 0xd1d6a58>
len(df_hour[df_hour['bj2016']>df_hour['gz2016']]), 1.0*len(df_hour[df_hour['bj2016']>df_hour['gz2016']])/len(df_hour)
(5153, 0.657857781182178)
len(df_hour[df_hour['bj2016']<df_hour['gz2016']]), 1.0*len(df_hour[df_hour['bj2016']<df_hour['gz2016']])/len(df_hour)
(2581, 0.32950338312268607)
从上述结果中看出,
广州地区2016年有5153次PM2.5测量值比北京同期小,占比65.8%,
有2581次比北京同期大,占比33%。
可以从总体上来说,广州的空气质量比北京好。
也可以画出曲线图进行更直观的对比。
df_hour.ix[:, ['bj2016','gz2016']].plot(title='2016 PM2.5 Hourly Beijing vs Guangzhou', figsize=(12,4))
<matplotlib.axes._subplots.AxesSubplot at 0xd6834a8>
3. 分析结论
根据美国大使馆/领事馆的PM2.5测量数据,可以得出以下结论:
- 广州的空气质量总体还是不错的,质量等级健康占82.1%,中等占16.3%,也就是说绝大多数时段的空气质量都比较好。
- 2016年与2015年相比,广州市的空气质量是有所改善,改善幅度不是很大
- 2016年,广州的空气质量比北京要好很多
当然,以上分析结论都是基于美国大使馆/领事馆的测量数据,受到测量仪器的准确性、测量点的地理位置等因素的影响。
4. 总结
本文通过一个PM2.5数据分析的案例,对Python数据分析的技术和方法进行了一次演练。其中主要用到了Python pandas包,想要更详细地了解pandas包,可以访问官方网站:http://pandas.pydata.org/ ,其中API文档:http://pandas.pydata.org/pandas-docs/stable/api.html
Python数据分析练习:北京、广州PM2.5空气质量分析(2)相关推荐
- Python数据分析练习:北京、广州PM2.5空气质量分析(1)
由于雾霾问题,全社会都很关注空气质量,政府也花了很多钱力图改善空气质量.我们作为城市市民经常要问:我们城市的空气质量到底怎样?这几年我们城市的空气质量是在改善还是恶化?我们城市的空气质量与其他城市相比 ...
- Python数据分析系列(2)——美国纽约皇后区空气质量分析
感谢关注天善智能,走好数据之路↑↑↑ 欢迎关注天善智能,我们是专注于商业智能BI,人工智能AI,大数据分析与挖掘领域的垂直社区,学习,问答.求职一站式搞定! 天善智能社区地址:https://www. ...
- python空气质量分析报告_Python数据可视化:2018年北上广深空气质量分析
原标题:Python数据可视化:2018年北上广深空气质量分析 作者:法纳斯特,Python爱好者,专注爬虫,数据分析及可视化 就在这周偶然看到一个学弟吐槽天津的空气,不禁想起那段厚德载雾,自强不吸的 ...
- python空气质量分析与预测_干货!如何用 Python+KNN 算法实现城市空气质量分析与预测?...
原标题:干货!如何用 Python+KNN 算法实现城市空气质量分析与预测? 作者 | 李秋键 责编 | 伍杏玲 封图 | CSDN 付费下载自东方 IC 出品 | CSDN(ID:CSDNnews) ...
- 基于Python的2013-2018全国城市空气质量分析
基于Python的2013-2018全国城市空气质量分析 项目摘要 本项目使用pandas/numpy工具包对557424条空气质量数据进行导入及清洗,并使用matplotlib/seaborn/py ...
- PySpark学习案例——北京空气质量分析
下方有数据可免费下载 目录 原始数据 环境 各个组件所遇到的问题 各种webUI端口 Python代码 azkaban调度 kibana可视化 原始数据 下载数据: 请点击我.提取码:736f 或者登 ...
- 五、空气质量分析与结果展示
五.空气质量分析与结果展示 5.1 实验背景 近年来随着城市化和工业化的发展,城市空气质量越来越差,从中央到地方各级政府对城市空气质量也越发重视.并对全国各个城市的空气质量进行了长期的采样.下面对全国 ...
- 城市空气质量分析与预测
城市空气质量分析与预测 一.AQI分析与预测 1.背景信息 2.任务说明 3.数据集描述 二.数据分析流程 基本流程 三.读取数据 1.导入相关的库 2.加载数据集 四.数据清洗 1.缺失值 1.1. ...
- Python基于Django城市PM2.5空气质量数据可视化分析
开发软件:Pycharm + Python3.7 + Django + Echarts + Mysql 实现目标:利用已经收集各个城市包括北京.上海.广州.成都.沈阳的PM2.5空气数据,利用pyth ...
最新文章
- 自己动手设计RESTful API
- python删除重复值所在的行数_使用python读取txt文件的内容,并删除重复的行数方法...
- 过滤器在图纸上的符号_终于找全了,施工图纸上那一堆难记的符号,赶紧收藏!...
- DCASE 2013任务1(声学场景分类)参赛作品相关信息
- ImportError: No module named 'chardet'
- MYSQL数据库默认latin1字符集转换为GBK或UTF8
- asp.net中的post和get请求操作
- verilog模块自动例化perl脚本
- pdf分页分片预览,pdf截取,pdf转图片
- 企业入职测试题目及答案_[企业入职性格测试题以及答案信息] 新员工入职性格测试题...
- ctfshow菜狗杯webshell wp
- 坑爹的No matching method
- js splice的三个用法
- Java实现-数字组合1
- 西电保研至东南经验贴
- 附子理中丸,人参健脾丸,参苓白术散、补脾益肠丸、痛泻宁颗粒
- UT源码_105032014126(改)
- PyTorch模型搭建和源码详解
- 运用Excel进行数据分析
- 神经科学探索脑第二章答案
热门文章
- 黄金矿工两百行基于Easyx
- C/C++关于行末空格的控制输出
- 【Web技术】1091- 跨浏览器窗口 ,7种方式,你还知道几种呢?
- 礼是随还是不随,年轻人该如何选择?
- Genymotion - 强大好用高性能的 Android 模拟器 (在电脑流畅运行APK安卓软件游戏的利器)
- 计算机图形学(四)几何变换_5_三维空间的几何变换_1_三维平移
- 综合练习Java算法
- PAT 乙级 1100 校庆
- java毕业设计旅游网站设计源码+lw文档+mybatis+系统+mysql数据库+调试
- java验证字符是否为字母_Java程序检查字符是否为字母