Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
271 views
in Technique[技术] by (71.8m points)

r - ggmap with geom_map superimposed

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(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 can't:

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

Some versions:

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

I can add geom_polygon to ggplot or ggmap and it works as expected. So something is up with geom_map....

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The error message is, I think, the result of an inheritance issue. Typically, it comes about when different data frames are used in subsequent layers.

In ggplot2, every layer inherits default aes mappings set globally in the initial call to ggplot. For instance, ggplot(data = data, aes(x = x, y = y)) sets x and y mappings globally so that all subsequent layers expect to see x and y in whatever data frame has been assigned to them. If x and y are not present, an error message similar to the one you got results. See here for a similar problem and a range of solutions.

In your case, it's not obvious because the first call is to ggmap - you can't see the mappings nor how they are set because ggmap is all nicely wrapped up. Nevertheless, ggmap calls ggplot somewhere, and so default aesthetic mappings must have been set somewhere in the initial call to ggmap. It follows then that ggmap followed by geom_map without taking account of inheritance issues results in the error.

So, Kohske's advice in the earlier post applies - "you need to nullify the lon aes in geom_map when you use a different dataset". Without knowing too much about what has been set or how they've been set, it's probably simplest to globber the lot by adding inherit.aes = FALSE to the second layer - the call to geom_map.

Note that you don't get the error message with ggplot() + myMap + Limits because no aesthetics have been set in the ggplot call.

In what follows, I'm using R version 2.15.0, ggplot2 version 0.9.1, and ggmap version 2.1. I use your code almost exactly, except for the addition of inherit.aes = FALSE in the call to geom_map. That one small change allows ggmap and geom_map to be superimposed:

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 

The result from the last line of code is:

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...