作者:戴维 · 卡尔&哈德利·威克姆
翻译:李博
原文地址:ggmap: Spatial Visualization with ggplot2
PS:由于原文较长,故翻译分为三次进行。
摘要:在空间统计中,数据可视化的实现,社会地标和地理环境创建的叠加模型是非常有价值的,而ggmap就是一个可通过谷歌地图中静态地图的空间信息,形象化展示的新工具,并通过 OpenStreet地图,Stamen地图或者CloudMade地图,使用ggplot2实现分层制图功能。
同时,还引入了几个新的实用的函数,并允许用户访问谷歌地理编码,距离矩阵和方向路线请求。其最终的结果是简洁、易懂且模块化的空间图形框架,并介绍了一些方便的空间数据分析工具。
00 - 简要介绍
在R中,可视化空间数据是一项具有挑战性的任务。
值得庆幸的是,这项任务通过sp、RgoogleMaps和相关的数据包(Pebesman和Bivand,2006年;,Bivand等人,2008年;Loecher和柏林经济和法律学院,2013年)的数据结构和绘图方法而变得更容易。
运用这些方法,个人就可以绘制出(比如)一个包含多边形区域数据的基本地理信息图或引用数据点的点图。然而,与专业的地理信息系统(GISs),如ESRI的ArcGIS,可以在地图和卫星图像上绘制出点,多边形等,并可使用下拉菜单相比,我们这些可视化还是有不尽人意的地方。
本文详细说明了使用ggplot2图形实现的分层语法,以及从Google maps、OpenStreetMap、Stamen maps或CloudMade maps(Wickham、2009年、2010年)中获得静态地图的相关信息,来实现在R中空间数据可视化的一些新方法。
比如使用名为ggmap的包就很容易上手。在描述ggmap的具体细节后,我们将展示其在德克萨斯州休斯顿市的暴力犯罪案件中的一些应用,并对一些实用功能做了概述。
01 - 在R中绘制空间数据
区域数据对应于具有多边形边界的地理区域数据。
一个典型的示例是每个邮政编码的居民人数。若仅考虑单位面积的边界, 我们习惯于在R中看到类似图1(左)的区域图。
图1:一副典型的R区域图——休斯顿地区的邮编(左),同时,右边是一副典型的R空间散点图——2010年1月到2010年8月在休斯顿发生的谋杀案(右)。
虽然这些类型的图很有用,但在很多情况下,并没有我们想要的那样翔实。比如,在绘制邮政编码的时候,也应该可以看到构成地面单位边界的主要道路和其它地标(事实上没有)。
点图中引用空间数据的情况往往效果更差。由于我们无法轻松地对没有任何背景信息的点的散点图进行上下文关联,所以通常可以添加一些区域数据的重叠点——无论何种数据都可用。结果如图1所示(右图)。
在大多数情况下,这个图形,对于在这个问题上研究了一段时间的人员来说是可以理解的,但对于读者来说可能用处不大。
读者必须努力将感兴趣的数据与他们的位置相关联。此外,还有许多被遗漏的细节——大多数事件发生在地标x的东面还是西面?它们是集中在城市的繁华区域,还是倾向于在偏僻区域发生?类似这样的问题用这些图形来回答不了,原因是我们不考虑小规模的区域边界(例如邮政编码或普查区)。
但,通过努力,可以制作出更好的地图,地图工具,sp或RgoogleMaps等工具更为容易;事实上,ggmap的灵感来自于RgoogleMaps(Becker等,2013; Bivand和Lewin-Koh,2013)。
此外,最近在大量在R制图中,出现了一种优秀的交互式GUI驱动的空间数据分析助推器包,该包基于Bing地图(Fellows等人,2013)。ggmap在基于ggplot2绘制框架定位的各种静态地图的语境信息上,又迈出了一步。
其展示结果是简洁,且大众可接受的一种绘图方式,并通过图形框架的分层语法保持图形的兼容性。其结果是类似图2的空间图。
图2:使用qmplot函数进行的Stamen Maps'terrain tile集合的空间散点图,本文中介绍了函数的实验融合。
02- 图形的分层语法
使用ggplot2制作绘图的一个优点是,ggplot2所基于的图形分层语法(Wickham,2010; Wilkinson,2005)。
根据定义,分层语法要求每个图由五个部分组成:
- 01.具有空间图像( aesthetic mappings)的默认数据集
- 02.一个或多个图层,每个图层都具有几何对象(“geom”),统计变换(“stat”)和具有空间图像(可能默认)的数据集)
- 03.每一个空间图像都有一个范围(可以自动生成)
- 04.一个坐标系
- 05.一个规范
由于ggplot2可以实现图形的分层语法,所以使用ggplot2绘制的每个图形都具有上述每个元素。因此,ggmap图也具有这些元素,但是其某些元素被固定到地图组件上:x轴为经度,y轴为纬度,坐标系被固定在墨卡托投影上。
使用分层语法绘制地图的主要理论优势是坐标尺度保持一致。在地图涵盖数据范围的典型情况下,在ggmap中,纬度和经度数值范围会限定地图(默认情况下),以及坐标轴上的刻度。每个图层呈现的颜色,填充,阿尔法混合和其它建立在地图之上的各个要素都保持了尺度的一致性。
语法的一致性对于分面图同样重要,目的是便于相同的要素在几个图中进行恰当的比较。当然,如果用户指定的空间数据出了问题,那么比例尺寸同样是有问题的,比如在同一张地图中使用多个投影,而要修复这些错误是困难的。
使用语法的优点是你能做的更好。由于图形在ggplot2中完成,所以用户可以使用ggplot2的全部功能,绘制优雅的可视内容——几何,统计,缩放等。在图2中已经看到这一点,qmplot的参数与ggplot2的qplot相同。
03 -ggmap 的工作原理
ggmap的基本思路是使用下载的地图图像,使用ggplot2将其作为背景层,然后在地图上绘制数据,统计信息或模型等图层。
在ggmap中,这个过程被分成两部分:
(1)下载图像并对它们进行格式化,使用get_map完成。
(2)使用ggmap完成绘图。
qmap将这两个函数结合起来,用于快速绘制绘图(c.f. ggplot2的ggplot),并且qmplot尝试将整个绘图过程封装成一个简单的命令(c.f.ggplot2的qplot)。
04 - get_map函数
在ggmap中,使用get_map函数完成地图下载并格式化图像,以进行绘图准备。
更具体地说,get_map是get_googlemap,get_openstreetmap,get_stamenmap和get_cloudmademap的一个复合函数,它接受一系列广泛的参数,并返回一个分类栅格对象,供ggmap绘图使用。
由于地图最大的且重要的是位置信息,所以get_map最为重要的参数是位置参数。
理想情况下,位置是指定地图中心经纬度,并附有参数的缩放。eg.从3到20的整数说明围绕中心的空间范围大小——3为陆地水平,而20为单一建筑水平,位置默认为德克萨斯州休斯顿市中心,并且缩放到10倍,大致为城市规模。
当经纬度作为理想情况下的位置说明而使用时,可操作性不是很强。基于这个原因,位置也接受一个字符串,无论这个字符串是否包含了地址、邮编、或者专有名称,都将通过编码函数,为地图中心赋予适当的经纬度坐标。
换句话说,我们并不需要知道地图中心精确地经纬度坐标,** get_map**能给于更为规范通俗的说明,从而轻松搞定。
例如:
>geocode("the white house")
lon lat
-77.03676 38.89784
文中“the white house”是一个具体位置,文章末尾有更多关于geocode和其它实用的函数的讨论。
一些用户发现了更为方便的边界框规范,可代替中心/缩放规范,为了适应这种形式的规范,位置还接受左/下/右/上四个长度数字向量的规范。目前此设置不适用于Google地图。
然而每个地图源都有它自己的Web应用程序接口(API),在get_map文本中,通过计算适当的参数(如果需要)来定位/放大,并把它们传递给每个API的具体get_ *函数。
为确保不同来源的地图,具有统一的位置/缩放的规格,get_map首先抓取适当的谷歌地图,确定其边界,然后下载所需要的其它地图。
在 Stamen地图和CloudMade Maps的情况下,这涉及到一个地图合成过程(小的地图图片),然后合成将结果,裁剪为适当边界框图。
从图3(谷歌和开放街道地图)中可以看到,四副地图源规范一致的排列为单一图形框。
baylor <- "baylor university"
qmap(baylor, zoom = 14)
qmap(baylor, zoom = 14, source = "osm")
上面的两幅图,get_map使用单一简单的语法为Google Maps(上)和OpenStreetMaps(下)提供了相同的空间范围,即使它们的API完全不同。
在涉及source和maptype参数之前,需要注意的是,get_map底层API特定的get_ *函数是一个包装器,它提供了更广泛的从各自的源下载的机制。
例如,get_googlemap可以访问Google Static Maps API的全部范围,如图4所示。
05 - get_map的source和maptype参数
使用不同的地图源(Google Maps,OpenStreetMap,Stamen Maps和CloudMade Maps)最有吸引力的方面是,制作人提供的不同地图样式。
set.seed(500)
df <- round(data.frame(
x = jitter(rep(-95.36, 50), amount = .3),
y = jitter(rep( 29.76, 50), amount = .3)
), digits = 2)
map <- get_googlemap(’houston’, markers = df, path = df, scale = 2)
ggmap(map, extent = ’device’)
这些指定与get_map的maptype参数,并且必须与源参数一致。一些大的道路,其它水域,还有一些地理位置的边界。有些更适合在黑白介质中绘图;别人只是很高兴看。
本节将介绍ggmap中可用的各种地图样式。
谷歌提供了四中不同类型——地形(默认),卫星(例如图13),路线图和混合图(例如图12)。另一方面,OpenStreetMap只提供如图3所示的默认样式。
Stamen地图和CloudMade地图真正的亮点是其风格迥异。
Stamen Maps有三个可用的类型(类似于瓷砖) - 地形(例如图2或13),水彩和调色剂(后两个见图5)
qmap(baylor, zoom = 14, source = "stamen", maptype = "watercolor")
qmap(baylor, zoom = 14, source = "stamen", maptype = "toner")
(图5: Stamen tile sets maptype = "watercolor(水彩)" and maptype = "toner(调色剂)" )
Stamen的地形块集与Google相似,但显而易见的是,水彩和瓷砖组与四个Google瓷砖组中的任何一个都差异巨大。
例如,后者是黑白绘图的理想选择(图5右)。
CloudMade地图通过允许用户(1)在数千个用户设置中进行选择,或(2)使用简单的在线编辑器创建一个全新的风格,用户可以指定颜色,线条等,从而进一步获得了瓷砖样式( tile styling )。对于各种类型的道路,水路,地标等,都由CloudMade生成,并可在ggmap中访问。
ggmap,通过get_map(或get_cloudmademap)允许两个选项。这是CloudMade Maps的一个独特功能,它真正提升了它们的适用性,并扩展了ggmap的发展前景。使用CloudMade Maps的一个小小的缺点是,用户必须向CloudMade注册以获取API密钥,然后将API密钥通过api_key参数传递给get_map。 API密钥是免费的,可以在几分钟内获得。
图6中可以看到两个低光的CloudMade地图样式。请注意,地图样式仅适用于拥有它们的用户。
Stamen Maps和CloudMade Maps都使用OpenStreetMap数据构建。这些数据由开放社区的在线用户提供,与维基百科创建方式大致相同——两者都是免费的,都是用户贡献的,两者都易于编辑。
此外,OpenStreetMap不仅具道路和水域的数据,还包括个别建筑物,喷泉,停车标志等细节。缺点是(像谷歌地图)并不是所有的位置都具有相同的精确度,并且缺陷可能会在小型地图时更为明显。
(未完待续)......
“本译文仅供个人研习、欣赏语言之用,谢绝任何转载及用于任何商业用途。本译文所涉法律后果均由本人承担。本人同意平台在接获有关著作权人的通知后,删除文章。”