ggmap с наложенным geom_map

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)

Создайте фрейм данных с длинной, широтой, 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, и укрепите (витаминами и железом?)

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 что-то не так ....


person Spacedman    schedule 07.06.2012    source источник


Ответы (1)


Сообщение об ошибке, я думаю, является результатом проблемы наследования. Обычно это происходит, когда на последующих уровнях используются разные фреймы данных.

В ggplot2 каждый уровень наследует сопоставления aes по умолчанию, установленные глобально при первоначальном вызове ggplot. Например, ggplot(data = data, aes(x = x, y = y)) устанавливает отображения x и y глобально, так что все последующие уровни ожидают увидеть x и y в любом фрейме данных, который был им назначен. Если x и y отсутствуют, появится сообщение об ошибке, подобное тому, которое вы получили. См. здесь аналогичную проблему и спектр решений.

В вашем случае это не очевидно, потому что первый вызов - это ggmap - вы не можете видеть сопоставления и то, как они установлены, потому что ggmap все красиво обернуто. Тем не менее, ggmap где-то вызывает ggplot, поэтому эстетические сопоставления по умолчанию должны быть установлены где-то при первоначальном вызове ggmap. Из этого следует, что ggmap, за которым следует geom_map без учета проблем наследования, приводит к ошибке.

Таким образом, применяется совет Кохске в предыдущем посте - «вам нужно обнулить lon aes в geom_map, когда вы используете другой набор данных». Не зная слишком много о том, что было установлено или как они были установлены, вероятно, проще всего выделить участок, добавив inherit.aes = FALSE ко второму уровню - вызов geom_map.

Обратите внимание, что вы не получаете сообщение об ошибке с ggplot() + myMap + Limits, потому что в вызове ggplot не задана эстетика.

Далее я использую R версии 2.15.0, ggplot2 версии 0.9.1 и ggmap версии 2.1. Я использую ваш код почти точно, за исключением добавления inherit.aes = FALSE при вызове geom_map. Это небольшое изменение позволяет накладывать ggmap и geom_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 

Результат последней строки кода:

введите описание изображения здесь

person Sandy Muspratt    schedule 07.06.2012
comment
Я получаю сообщение об ошибке в validDetails.polygon (x): 'x', 'y' и 'id' должны иметь одинаковую длину, если я добавляю inherit.aes = FALSE в myMap в приведенном выше примере. - person Spacedman; 08.06.2012
comment
@Spacedman Я отредактировал свой ответ, включив в него код и результат. Код почти полностью совпадает с вашим кодом, за исключением добавления inherit.aes = FALSE в вызове geom_map. - person Sandy Muspratt; 08.06.2012
comment
Я обновил ggplot2 и ggmap до этих версий, и теперь ggplot2 полностью сломан. Первый пример в geom_point создает график без точек, просто устанавливает оси, серый цвет b / g и ничего. Из R --vanilla без загруженных других пакетов. Может быть, версия R (2.14.2 ...). Grr. - person Spacedman; 08.06.2012
comment
Да, вроде работает с 2.15, странности с R 2.14. Время обновления. - person Spacedman; 08.06.2012
comment
@Spacedman Я должен был упомянуть версию R - я, кажется, помню нечто подобное с R2.14. Я переписал пост, добавив объяснение наследования эстетической проблемы. - person Sandy Muspratt; 09.06.2012
comment
inherit.aes = FALSE - arrrrgh - person Raffael; 07.07.2014