ggmap 与 geom_map 叠加

Posted

技术标签:

【中文标题】ggmap 与 geom_map 叠加【英文标题】:ggmap with geom_map superimposed 【发布时间】:2012-06-11 10:39:27 【问题描述】:
library(sp)
library(spdep)
library(ggplot2)
library(ggmap)
library(rgdal)

获取和摆弄数据:

nc.sids <- readShapePoly(system.file("etc/shapes/sids.shp", package="spdep")[1],ID="FIPSNO", proj4string=CRS("+proj=longlat +ellps=clrk66"))
nc.sids=spTransform(nc.sids,CRS("+init=epsg:4326"))

从 stamen.com 获取背景图,情节,看起来不错:

ncmap = get_map(location=as.vector(bbox(nc.sids)),source="stamen",maptype="toner",zoom=7)
ggmap(ncmap)

创建一个带有 long、lat、Z 的数据框,并在地图上绘制一个空白图:

ncP = data.frame(coordinates(nc.sids),runif(nrow(nc.sids)))
colnames(ncP)=c("long","lat","Z")

ggmap(ncmap)+geom_point(aes(x=long,y=lat,col=Z),data=ncP)
ggplot()+geom_point(aes(x=long,y=lat,col=Z),data=ncP)

给它一些独特的 id,称为“id”并强化(用维生素和铁?)

nc.sids@data[,1]=1:nrow(nc.sids)
names(nc.sids)[1]="id"
ncFort = fortify(nc.sids)

现在,我的地图和我的极限,我想绘制 74 岁的出生率:

myMap = geom_map(aes(fill=BIR74,map_id=id),map=ncFort,data=nc.sids@data)
Limits = expand_limits(x=ncFort$long,y=ncFort$lat)

我可以在空白处:

ggplot() + myMap + Limits

但在 ggmap 上我不能:

ggmap(ncmap) + myMap + Limits
# Error in eval(expr, envir, enclos) : object 'lon' not found

一些版本:

> packageDescription("ggplot2")$Version
[1] "0.9.0"
> packageDescription("ggmap")$Version
[1] "2.0"

我可以将 geom_polygon 添加到 ggplot 或 ggmap 并按预期工作。所以 geom_map 出了点问题......

【问题讨论】:

【参考方案1】:

我认为错误消息是继承问题的结果。通常,在后续层中使用不同的数据帧时会出现这种情况。

在 ggplot2 中,每一层都继承了在初始调用 ggplot 时全局设置的默认 aes 映射。例如,ggplot(data = data, aes(x = x, y = y)) 全局设置 x 和 y 映射,以便所有后续层都希望在分配给它们的任何数据帧中看到 xy。如果xy 不存在,则会出现与您得到的结果类似的错误消息。 See here 用于类似问题和一系列解决方案。

在您的情况下,这并不明显,因为第一次调用是对ggmap - 您看不到映射,也看不到它们是如何设置的,因为ggmap 已经很好地包装了。尽管如此,ggmap 在某处调用了ggplot,因此默认美学映射必须在最初调用ggmap 时设置在某处。那么ggmap后跟geom_map不考虑继承问题就会导致错误。

因此,Kohske 在较早的帖子中的建议适用 - “当您使用不同的数据集时,您需要取消 geom_map 中的 lon aes”。在不太了解已设置的内容或设置方式的情况下,将inherit.aes = FALSE 添加到第二层(对geom_map 的调用)可能是最简单的。

请注意,您不会收到带有 ggplot() + myMap + Limits 的错误消息,因为在 ggplot 调用中没有设置美学。

接下来,我使用的是 R 版本 2.15.0、ggplot2 版本 0.9.1 和 ggmap 版本 2.1。我几乎完全使用您的代码,除了在对geom_map 的调用中添加了inherit.aes = FALSE。这一点小小的改动让ggmapgeom_map 可以叠加:

library(sp)
library(spdep)
library(ggplot2)
library(ggmap)
library(rgdal)

#Get and fiddle with data:
nc.sids <- readShapePoly(system.file("etc/shapes/sids.shp", package="spdep")[1],ID="FIPSNO", proj4string=CRS("+proj=longlat +ellps=clrk66"))
nc.sids=spTransform(nc.sids,CRS("+init=epsg:4326"))

#Get background map from stamen.com, plot, looks nice:
ncmap = get_map(location=as.vector(bbox(nc.sids)),source="stamen",maptype="toner",zoom=7)
ggmap(ncmap)

#Create a data frame with long,lat,Z, and plot over the map and a blank plot:
ncP = data.frame(coordinates(nc.sids),runif(nrow(nc.sids)))
colnames(ncP)=c("long","lat","Z")

ggmap(ncmap)+geom_point(aes(x=long,y=lat,col=Z),data=ncP)
ggplot()+geom_point(aes(x=long,y=lat,col=Z),data=ncP)

#give it some unique ids called 'id' and fortify (with vitamins and iron?)
nc.sids@data[,1]=1:nrow(nc.sids)
names(nc.sids)[1]="id"
ncFort = fortify(nc.sids)

#Now, my map and my limits, I want to plot the 74 birth rate:
myMap = geom_map(inherit.aes = FALSE, aes(fill=BIR74,map_id=id), map=ncFort,data=nc.sids@data)
Limits = expand_limits(x=ncFort$long,y=ncFort$lat)

# and on a blank plot I can:
ggplot() + myMap + Limits

# but on a ggmap I cant:
ggmap(ncmap) + myMap + Limits 

最后一行代码的结果是:

【讨论】:

如果我在示例中将inherit.aes=FALSE 添加到myMap,我得到“validDetails.polygon(x) 中的错误:'x' 和'y' 和'id' 的长度必须相同”以上。 @Spacedman 我已经编辑了我的答案以包含代码和结果。除了在geom_map 调用中添加inherit.aes = FALSE 之外,该代码几乎与您的代码完全相同。 我将 ggplot2 和 ggmap 更新到了这些版本,现在 ggplot2 完全崩溃了。 geom_point 中的第一个示例生成了一个没有点的图,只设置了轴、灰色 b/g,什么都没有。来自没有加载其他包的 R --vanilla。也许是 R 版本的东西(2.14.2...)。 Grr. 是的,似乎与 2.15 一起工作,与 R 2.14 一起工作很奇怪。升级时间。 @Spacedman 我应该提到 R 版本 - 我似乎记得与 R2.14 类似的东西。我重新写了帖子,增加了对美学继承问题的解释。

以上是关于ggmap 与 geom_map 叠加的主要内容,如果未能解决你的问题,请参考以下文章

GIS | R 数据可视化:ggmap包

arcgis 怎样实现栅格图与矢量图动态叠加显示。

两幅图像的融合与叠加

数据结构与算法之深入解析“重复叠加字符串匹配”的求解思路与算法示例

叠加装饰器与迭代器

在android中与相机捕获的图像叠加图像