2019独角兽企业重金招聘Python工程师标准>>>

原创文章,欢迎分享!    http://my.oschina.net/u/2306127/blog/613875

最近空气污染严重,也为了演练一下Orange插件编写和数据处理的学习成果,准备开发一个AQI数据获取和分析的插件。目前做出来的一个样子如下,还有点酷吧?[下一步完善后,会将源码共享,目前暂不拿来误人,感兴趣的可交流]

研究过程中,也发现一个重要的趋势:北京的空气质量在整个华北平原地区,几乎任何时候都是最好的!

这里主要介绍研究过程,目前结论只是初步观察,后面研究再提供相应的分析图表。

过程中遇到的问题和处理办法,与大家分享,也有一些未决的问题,看哪位牛人可以解决:

1、从网页上抓取AQI数据

数据来源用的http://aqicn.org。使用requests这个库进行数据抓取,功能很强,尤其是可以自定义Header。如果不自定义header,由于这个网站采用了反抓取技术,只返回过期的老数据,是无法得到最新的数据的。代码如下:

#Get AQI data from web,by a region.
def getaqidata(left,right,bottom,top):aqi_url = geturl(left,right,bottom,top)    aqi = requests.get(aqi_url,headers=gethead())raqi = aqi.textraqi2 = re.search(r'\[\{.*\}\]',raqi)  cities = json.loads(raqi2.group(0))return cities

具体的Header可以打开FireFox的“开发者”功能,选择“网络”,再选中当前的数据访问请求列表,即可看到所有的消息。然后选择“原始头“,即可将相应的head拷贝下来,放到gethead()函数下,做成一个辞典返回。然后调用:

aqi = requests.get(aqi_url,headers=gethead())

返回的值是一个json的字符串,但是有一些头信息,如下:

mapShowLevel2Makers([{"lat":"38.871","lon":"115.521","aqi":"112",
"utime":" on Thursday, Feb 4th 2016, 16:00 pm","stamp":1454572800,
"city":"City Monitoring Station, Baoding",
"img":"_c_az8khNSs3Uf7J_7tN1s57uaNIH4uezJz7b2v189UwA",
"pol":"pm25","tz":"+0800","idx":781,"x":668},
{"lat":"38.896","lon":"115.522","aqi":"93",
"utime":" on Thursday, Feb 4th 2016, 16:00 pm","stamp":1454572800,
"city":"Huadian II, Baoding",
"img":"_AR8A4P9DTjpIZWJlaS_kv53lrprluIIv5Y2O55S15LqM5Yy6",
"pol":"pm25","tz":"+0800","idx":783,"x":670},...{"lat":"40.152","lon":"118.311","aqi":"48",
"utime":" on Thursday, Feb 4th 2016, 16:00 pm","stamp":1454572800,
"city":"Qianxi EPA, Tangshan",
"img":"_ASUA2v9DTjpIZWJlaS_llJDlsbHluIIv6L-B6KW_546v5L-d5bGAKCop",
"pol":"pm25","tz":"+0800","idx":823,"x":4640}],
[7.8,0]);

使用正则表达式把数据提取出来,放到cities中。

raqi2 = re.search(r'\[\{.*\}\]',raqi)

2、AQI数据的解析

提取的cities内容如下:

[{"lat":"38.871","lon":"115.521","aqi":"112",
"utime":" on Thursday, Feb 4th 2016, 16:00 pm","stamp":1454572800,
"city":"City Monitoring Station, Baoding",
"img":"_c_az8khNSs3Uf7J_7tN1s57uaNIH4uezJz7b2v189UwA",
"pol":"pm25","tz":"+0800","idx":781,"x":668},
{"lat":"38.896","lon":"115.522","aqi":"93",
"utime":" on Thursday, Feb 4th 2016, 16:00 pm","stamp":1454572800,
"city":"Huadian II, Baoding",
"img":"_AR8A4P9DTjpIZWJlaS_kv53lrprluIIv5Y2O55S15LqM5Yy6",
"pol":"pm25","tz":"+0800","idx":783,"x":670},...{"lat":"40.152","lon":"118.311","aqi":"48",
"utime":" on Thursday, Feb 4th 2016, 16:00 pm","stamp":1454572800,
"city":"Qianxi EPA, Tangshan",
"img":"_ASUA2v9DTjpIZWJlaS_llJDlsbHluIIv6L-B6KW_546v5L-d5bGAKCop",
"pol":"pm25","tz":"+0800","idx":823,"x":4640}]

cities是一个标准的列表,其中包含一个dict对象,里面有若干个key-value数值对。

cities可以使用标准的json操作或者python的list进行访问。

3、转为Pandas.DataFrame

pandas有非常丰富的数据操作函数,pandas可以直接将上面的cities数据结构转为一个pandas.DataFrame。

import pandas as pd
df = pandas.DataFrame(cities)

也可以使用pandas.DataFrame.to_csv()将数据保存到csv文件中,或者直接存为excel的表格,然后...可以干很多事了。

4、转为GeoPandas.GeoDataFrame

GeoPandas带有Geometry字段,可以保存几何对象信息。可以将pandas.DataFrame的lon/lat字段转为点对象,但是保存到shp时会出现失败,将文本字段去除后就可以(查看数据发现拼音等字符,有可能未处理当成非法字符了),暂时想了个办法绕过去。

def aqi2geopandas(cities):df = pd.DataFrame(cities)    ps = []ps0 = [1]ns = []ns0 = [1]for index, row in df.iterrows():print(index,':',row['lat'],'-',row['lon'])ps0[0] = Point(float(row['lon']),float(row['lat']))addr = row["city"].split(",")if len(addr) >= 1:ns0[0] = addr[len(addr)-1]else:ns0[0] = "noname"ps.append(ps0[0])ns.append(ns0[0])gs = GeoSeries(ps,crs={'init': 'epsg:4326', 'no_defs': True})        geodf = GeoDataFrame({'id' : df["x"],'name' : ns, 'lon' : df["lon"],'lat' : df["lat"],'aqi' : df["aqi"],'utime' : df["utime"],'tz' : df["tz"],'geometry' : gs})return geodf

如果可以直接转换,上面的代码还可以大大简化的。先实现得到数据再说,功能代码后面再去研究、优化。

5、保存AQI数据为shp文件

#得到GeoPandas对象。
gdf = aqi2geopandas(cities)#fshp是要保存的文件名。
gdf.to_file(fshp)

6、转为Orange.data.Table

这个过程中遇到一些问题,主要是Orange.data.Table对象构造时文本对象加不进去,有些API不知道用法,看了源代码没有完全明白,后面再研究。目前采用保存到.tab文件,再读入的方法,试过可以用,只是需要创建临时文件,性能上会有不足。

def reformcity_tab(i,city):rinfo = str(i+1)+"\t"rinfo = rinfo+city["lat"]+"\t"rinfo = rinfo+city["lon"]+"\t"rinfo = rinfo+city["aqi"]+"\t"rinfo = rinfo+city["city"]+"\t"addr = city["city"].split(",")if len(addr) == 0:rinfo = rinfo+"\t-\t-\t-\t"if len(addr) == 1:rinfo = rinfo+addr[0]+"\t-\t-\t"if len(addr) == 2:rinfo = rinfo+addr[1]+"\t"+addr[0]+"\t-\t"if len(addr) >= 3:rinfo = rinfo+addr[2]+"\t"+addr[1]+"\t"+addr[0]+"\t"rinfo = rinfo+city["utime"]+"\t"rinfo = rinfo+city["tz"]#print("$",rinfo)return rinfodef writecityname_tab(cities,Filename):print("#Write to File:",Filename,"...")f = open(Filename, 'w')f.write("ID\tLatitude\tLongitude\tAQI\tNAME\tPROV\tCONT\tSTA\tUTIME\tTZ" + "\n")f.write("discrete\tdiscrete\tdiscrete\tdiscrete\tdiscrete\tdiscrete\tdiscrete\tdiscrete\tdiscrete\tdiscrete" + "\n")f.write(" \t \t \t \t \t \t \t \t" + "\n")for i, city in enumerate(cities):try:rinfo = reformcity_tab(int(city["x"]),city)f.write(rinfo + "\n")#print(city)except Exception as err:print("#ERROR: ",err)continuef.close()print("#Write AQI to Orange.data.Table Finished.")

然后读入.tab文件:

# ftable为上面保存的文件名,一定要一样哦。
self.table = Orange.data.Table(ftable)

目前已经可以从网上按照指定区域抓取AQI数据,然后转为Orange.data.Table,以及Pandas.DataFrame和 GeoPandas.DataFrame的数据对象,并且通过GeoPandas.DataFrame.to_file(fname)转为shp文件,然后可以在各种GIS软件和R等数据分析软件中打开,进行后续的分析和制图等操作,我使用QGIS打开了,没有问题。

转载于:https://my.oschina.net/u/2306127/blog/613875

编写一个AQI分析的Orange插件相关推荐

  1. 如何用vbs编写一个游戏_如何编写一个 SkyWalking 插件

    点击上方"开源社"关注我们 | 作者:vcjmhg| 编辑:李明康| 责编:袁睿斌 | 设计:叶修缘丶 1 概述 之前几篇文章,我们着重介绍了在对 SkyWalking 进行二次开 ...

  2. 如何编写一个抢购bot_如何编写一个SkyWalking插件

    概述 之前几篇文章,我们着重介绍了在对SkyWalking进行二次开发之前的环境搭建问题,因此本篇文章将基于SkyWalking-8.1.0版本,以开发webflux-webclent插件为例,分享一 ...

  3. 编写一个IDEA插件之:事件监听

    事件监听,我们最熟悉不过的就是开发APP时,监听按钮点击事件.手指触摸及移动事件.网络状态事件等等.事件监听大多通过观察者模式实现,首先API调用者不需要知道后台是如何检测出网络状态不可用的,而只需要 ...

  4. 从零开始编写一个vue插件

    title: 从零开始编写一个vue插件 toc: true date: 2018-12-17 10:54:29 categories: Web tags: vue mathjax 写毕设的时候需要一 ...

  5. 如何编写一个Jquery插件

    首先我们来搞清楚一些关于Jquery插件的知识: 一.插件的种类: 封装对象方法的插件 这种插件是将对象方法封装起来,用于对通过选择器获取的jQuery对象进行操作,是最常见的一种插件 封装全局函数的 ...

  6. Java黑皮书课后题第7章:7.4(分析成绩)编写一个程序,读入个数不确定的考试分数,并且判断有多少个分数是大于或等于平均分,多少个分数是低于平均分的。输入一个负数表示输入结束。假设最高分是100

    7.4(分析成绩)编写一个程序,读入个数不确定的考试分数,并且判断有多少个分数是大于或等于平均分,多少个分数是低于平均分的.输入一个负数表示输入结束.假设最高分是100 题目 题目描述 破题 代码 运 ...

  7. java插件开发_编写一个IDEA插件之:自动生成Java代码

    我很喜欢IDEA的一键自动生成代码功能,例如自动生成构造方法.字段的Get/Set方法.ToString方法等等,除此之外,也有一些插件提供自动生成代码的功能,例如我们所熟悉的GsonFormat插件 ...

  8. 怎么编写一个chrome插件

    怎么编写一个chrome插件 总觉得chrome插件这种东西很高端,很遥不可及.当然复杂的chrome插件开发起来确实比较困难,但是我们可以从一个简单的chrome插件demo慢慢入手,了解一下chr ...

  9. 编写一个VSCode插件

    原文链接: 编写一个VSCode插件 - 愧怍的小站 自从使用过 VSCode 后就再也离不开 VSCode,其轻量的代码编辑器与诸多插件让多数开发者爱不释手.同样我也不例外,一年前的我甚至还特意买本 ...

最新文章

  1. Python 单下划线(“_“)与双下划线(“__“)以及以双下划线开头和结尾的的区别
  2. 10个机器学习的JavaScript示例
  3. 安卓队列缓存文件,包括断点续传
  4. 二叉树的层次遍历_【腾讯面试热身题】二叉树层次遍历(动画展示)
  5. 数据结构(七)图的遍历(递归非递归方法)
  6. python 函数式编程 库_使用Python的toolz库开始函数式编程的方法
  7. 解除隐藏文件cmd命令_Win10用cmd命令隐藏文件|Win10相互转换隐藏真实文件
  8. python解决单调栈问题
  9. 数据结构单链表的创建和遍历(后插法)
  10. monkey命令常用参数与monkey事件百分比
  11. 大数据数据挖掘与云计算-认识大数据
  12. ubuntu-22.04.1磁盘分区和挂载
  13. python求15 17 23 65 97的因数_python练习题-答案
  14. PDF页码怎么设置?如何给PDF文件设置页码
  15. cx_Oracle.DatabaseError: DPI-1072: the Oracle Client library version is unsupported 已解决
  16. bitmap的六种压缩方式,Android图片压缩(转)
  17. 速知!二级建造师你满足报考要求吗?
  18. @Around简单使用示例——SpringAOP增强处理
  19. 【300+精选大厂面试题持续分享】大数据运维尖刀面试题专栏(九)
  20. zigbee学习参考(1~42 )

热门文章

  1. 联想电脑欲重返手机市场,首款机型揭秘
  2. PhotoShop中的切片功能
  3. SSL漏洞 TLS/SSL Sweet32 attack || TLS/SSL Wrak Cipher Suites[解决]
  4. iOS应用架构谈 -(2)view层的组织和调用方案
  5. Matplotlibseaborn笔记1--数据skewness与displot相关预处理
  6. 2020版IDEA安装教程
  7. 靠计划过生活不要靠运气过生活
  8. BricsCAD 22 Mac中文版 最强CAD设计平台
  9. 优化算法——牛顿法(Newton Method)
  10. CPython、IPython、PyPy、Jython、IronPython名词解释