这些年你都学了些什么

数据可视化 多年下来,我的Google Bookmarks里已经有近万条的书签。大部分内容是我在读过一遍之后就收藏起来的,也有很多看了一眼之后,觉得不错,然后收藏起来准备以后读的(当然,你也知道,再也没有打开过)。 有没有一个方法可以让我以可视化的方式,看到这些年我都学了那些东西呢?将书签列表作为源数据,然后将这些信息可视化出来会非常有意思:比如收藏夹中的热门词是什么,哪段时间收藏了多少条的书签(学习投入程度趋势)等等。 下图是我的书签中,排行前30的关键字排序。可以明显的看出,我对于JavaScript的喜爱程度相当高,对美食的喜爱也超过了python和linux。 这里我将使用python,结合python的一些库来实现书签可视化。简而言之,整个过程可以分成这样几个步骤: 将Google Bookmarks导出为本地文件 将书签文件解析为容易处理的内部格式(比如python的dict等) 由于书签中会有中文的句子,所以会涉及到分词 统计词语的频率,并绘制成图标 数据源 Google Bookmarks本身可以直接导出成HTML文件。该HTML文件包含了时间戳和书签的标题,我们可以通过python的库BeautifulSoup将HTML中的文本抽取出来: from bs4 import BeautifulSoup def load_bookmarks_data(): soup = BeautifulSoup(open('bookmarks_10_21_15.html').read(), "html.parser") return soup.get_text() if __name__ == "__main__": print load_bookmarks_data() BeautifulSoup提供非常好用的API来抽取结构化文档中的内容。 分词 BeautifulSoup获得的是一条条独立的句子,我们需要使用分词器将所有的句子分解成片段。这里我使用了jieba(结巴分词)分词器来完成这个任务: import jieba data = "我在出报表,你的博客写的怎么样了" seg_list = jieba.cut(data, cut_all=False) for seg in seg_list: print seg 将会输出: 我 在 出 报表 , 你 的 博客 写 的 怎么样 了 我们定义一个方法来将上一步中的文本分词: def extract_segments(data): seg_list = jieba....

November 1, 2015 2 min

Python中的List表达式

一个小故事 三年前,我在一篇博客里不无自豪的记录了python编写的小函数,当时感觉python真强大,11行代码就写出了一个配置文件的解析器。 def loadUserInfo(fileName): userinfo = {} file = open(fileName, "r") while file: line = file.readline() if len(line) == 0: break if line.startswith('#'): continue key, value = line.split("=") userinfo[key.strip()] = value.strip() return userinfo 最近正在跟同事学习python在数据挖掘中的应用,又专门学习了一下python本身,然后用list comprehension简化了以下上面的代码: def loadUserInfo(file): return dict([line.strip().split("=") for line in open(file, "r") if len(line) > 0 and not line.startswith("#")]) 这个函数和上面的函数的功能一样,都是读取一个指定的key=value格式的文件,然后构建出来一个映射(当然,在Python中叫做字典)对象,该函数还会跳过空行和#开头的行。 比如,我想要查看一下.wgetrc配置文件: if __name__ == "__main__": print(loadUserInfo("/Users/jtqiu/.wgetrc")) 假设我的.wgetrc文件配置如下: http-proxy=10.18.0.254:3128 ftp-proxy=10.18.0.254:3128 #http_proxy=10.1.1.28:3128 use_proxy=yes 则上面的函数会产生这样的输出: {'use_proxy': 'yes', 'ftp-proxy': '10.18.0.254:3128', 'http-proxy': '10.18.0.254:3128'} list comprehension(列表推导式) 在python中,list comprehension(或译为列表推导式)可以很容易的从一个列表生成另外一个列表,从而完成诸如map, filter等的动作,比如:...

March 30, 2015 2 min

使用Mapnik搭建GIS服务器

渲染引擎Mapnik 上一篇文章中大概介绍了Mapnik,它是一个渲染引擎,一般开发中都会使用他的python的bind做开发。 Mapnik的文档写的比较详细,我们这里只是做一些必要的介绍,详细的细节可以参看Mapnik在Github上的文档。 在Mac下,安装Mapnik十分容易,使用brew即可,注意我们在此处带上--with-postgresql选项,使得Mapnik可以通过PostGIS来访问数据库: brew install mapnik --with-postgresql 安装完成之后,可以通过一个小的python脚本来测试: import mapnik map = mapnik.Map(256, 256) map.background = mapnik.Color('red') map.zoom_all() mapnik.render_to_file(map, 'red.png', 'png') 这段脚本可以在当前目录下生成一个红色的256x256的小图片。好了,有了渲染引擎,我们需要一些数据来进行渲染了。 数据源 最通用的数据格式为Shapefiles,目前有很多的免费地理信息供公共下载,我们可以从Metro的站点上下载一些小的数据文件。 $ wget http://osm-extracted-metros.s3.amazonaws.com/chengdu.osm2pgsql-shapefiles.zip $ mkdir chengdu $ cd chengdu $ unzip chengdu.osm2pgsql-shapefiles.zip 这样就得到了一组文件: $ find . -name "*.shp" ./chengdu.osm-line.shp ./chengdu.osm-point.shp ./chengdu.osm-polygon.shp 每一个shp文件都会对应几个其他类型的文件,比如投影信息,属性表等。仅仅查看shp的话,有表示所有点的文件chengdu.osm-line.shp,又表示所有线的chengdu.osm-line.shp,以及表示所有面(区域)的chengdu.osm-polygon.shp文件。 有了这些文件,我们就可以做一些测试了,比如我们首先加载所有的线条,并根据这些线条生成一个图层: import mapnik map = mapnik.Map(800, 800) map.background = mapnik.Color('#ffffff') style = mapnik.Style() rule = mapnik.Rule() point_symbolizer = mapnik.PointSymbolizer() rule.symbols.append(point_symbolizer) style.rules.append(rule) map.append_style('default', style) ds_point = mapnik....

April 12, 2014 2 min

地理信息系统GIS简介

GIS系统如何工作 去年十二月中旬从RCA项目上下来之后,就一直在一个GIS项目上做咨询。在新的项目上,日常工作的重点主要是放在前端开发上(比如AngularJS,Grunt,Jamsine之类),对于业务(与GIS相关)方面,则完全没有涉及。 虽说之前也接触过一点GIS相关的开发,比如Google Maps API,OpenLayers之类,但是仅仅停留在使用别人的API搭建个小应用的层次。 直到最近,在GIS专家芦康平的指导下,才真正开始接触GIS,很快我就发现这是另一个十分好玩的新天地。简而言之,这个新的天地里,所有的东西都有一种似曾相识的感觉,但是又非常新鲜。比如地图服务器,渲染引擎,缓存,地理信息数据库等,都可以在其他的系统中找到对应。这种感觉好比收集硬币,或者收集邮票一样,当你看到新的有着不同花纹,大小,材质,年代的硬币时,那种既在意料之中又在意料之外的感觉简直太有意思了。 GIS系统,毋庸置疑可以帮助人们更加直观的分析数据,当数据与地理信息有所关联的时候,GIS系统会变得十分友好,也可以更充分的提供信息。 鉴于GIS对我来说是一个完全崭新的领域,那么学习之前,自然有很多的问题出现: 地图的信息(建筑物,河流,街道)从何而来? 数据在服务器端以何种方式存储? 地图数据到底如何被渲染出来? 一个GIS系统的部署结构是什么样的?需要哪些组件? 业界的标准是什么,有哪些开源的项目和工具可供参考? 等等。 地图是如何被渲染的? 通常来讲,我们看到的地图是由一个底图和若干个层的叠加来达到的最终结果。其中每个层次都会保存不同类型的地理信息,比如将所有的河流信息放在一个层,将建筑物放在另外一个层。 这些信息存储在数据文件中(shapefiles)或者数据库中,通过使用专门的工具来将这些地理信息转换成图片。由于每张图片都是透明的,这样叠加起来的最后效果就是如Google Maps之类应用的结果了。当然,叠加过程一般都发生在服务器端(有些简单应用则是在客户端完成某些层次的绘制,比如我之前发过的我去过的地方,这些热力图就是在客户端通过JavaScript加上去的。)。 地图在服务器端被渲染出来之后,尺寸一般会非常大。需要有工具将这些大图切分成很多组的小图,这些小图被称之为瓦片(tile)。为了给不同缩放级别的客户端提供不同的图片,这些瓦片被精心的分成了多个组,每个组都有编号。如果地图支持18级的缩放,就会现有18个分组。当然分组好越靠后,分组中的瓦片越多。 比如当客户端请求缩放级别为10的地图时,客户端(比如OpenLayers)会根据经纬度计算好图片的边界,然后请求第10级的一些瓦片,并将这些瓦片排列在画布上。一般而言,这些瓦片都是正方形(256x256或者512x512)。 WMS服务 WMS(Web Map Service)是一个基于HTTP的简单协议,客户端发送的请求中包含请求类型,地图的层次,边界等信息,服务器根据这个信息生成图片,并返回该图片: 当然,WMS本身支持多种请求,最常见的就是GetMap,细节可以参考OGC规范及具体服务器的实现。而对于后端的服务器来说,从请求中获取这些信息之后,会首先从数据库/数据文件中得到数据,并使用渲染引擎绘制图片,并最后将图片返回客户端。 图片类型 图片分为栅格类型和矢量类型两种。栅格图片一般的原始来源是航拍,遥感等,本质上来说是照片,照片必然会有大小,如果放大到某一个范围之外,就会模糊。而矢量图是数学上的抽象,比如在某个坐标系统中,在某处有一个点A,另一处有一个点B,两点之间有一条线连接。矢量图的特点是与缩放程度无关。 栅格图的特点是真实,矢量图的特点是抽象(存储方便,占用空间更少,也更容易修改)。但是为了绘制正确,完整的地图,两种类型的图片信息都是必要的: 常用文件格式 Shapefiles是Esri公司开发出来的用于存储地理信息的文件格式。说是文件,其实是一个文件族,Shapefile包含了数种文件,其中有三种必须的(.shp,.shx,.dbf)。其他有一些可选的(.prj,.sbn/.sbx等等)。 OSM格式是由OpenStreetMap采用的文件格式,其实是一个XML。 <osm version="0.6" generator="Osmosis 0.43.1"> <bounds minlon="144.26600" minlat="-38.55200" maxlon="145.81000" maxlat="-37.36500" origin="http://www.openstreetmap.org/api/0.6"/> <node id="579259" version="3" timestamp="2008-12-17T02:28:22Z" uid="57437" user="Canley" changeset="431325" lat="-37.9309048" lon="145.1282066"/> <node id="579260" version="5" timestamp="2009-12-03T21:42:45Z" uid="1679" user="andrewpmk" changeset="3284133" lat="-37.9388304" lon="145.1266866"/> <node id="579261" version="4" timestamp="2013-02-15T20:00:37Z" uid="79475" user="AlexOnTheBus" changeset="15043978" lat="-37.9404366" lon="145.1395848"/> <node id="579262" version="18" timestamp="2013-01-31T21:37:02Z" uid="79475" user="AlexOnTheBus" changeset="14864580" lat="-37....

April 10, 2014 1 min