geotheory geotheory - 1 month ago 12
R Question

ggplot omits polygon holes

I'm having difficulty getting ggplot to plot polygons that feature holes. The following demonstrates. First get the shapefile with

git clone https://github.com/geotheory/volcano
. Next:

require(ggplot2); require(ggmap); require(dplyr); require(maptools)
v = readShapePoly('volcano/volcano.shp')
v@proj4string = CRS('+proj=longlat +datum=WGS84')

# confirm polygons spatially exclusive (don't overlap)
plot(t(bbox(v)), type='l', lwd=8)
plot(v, col=paste0(colorRampPalette(c('grey','red'))(8),'dd'), add=T)


enter image description here

Looks ok. A
dd
alpha should render the line invisible if obscured by multiple polygons. Now let's try in ggplot.

d = fortify(v) %>% as_data_frame()
bb = bbox(v)
toner = get_stamenmap(c(bb[1,1], bb[2,1], bb[1,2], bb[2,2]), zoom=11, maptype='toner')
ggmap(toner) + geom_polygon(data=d, aes(long, lat, group=group, fill=id), alpha=.5)


enter image description here

Central polygons must be overlapping since the underlying map is completely obscured in the centre. Let's check the fortified data for holes:

d %>% select(id, hole) %>% table()
hole
id FALSE TRUE
0 278 0
1 715 0
2 392 388
3 388 331
4 390 265
5 265 387
6 328 125
7 125 0


Looks ok, so let's try visualising them individually.

i = 3
plot(v[i,], col='red')
ggplot(filter(d, id == i-1)) + geom_polygon(aes(long, lat, group=group, col=hole), fill=NA)
ggplot() + geom_polygon(data=filter(d, id==i-1), aes(long,lat, group=group))


enter image description here

Something appears to be going wrong. ggplot seems to be ignoring the holes. Unless it's a problem with the shapefile. Any suggestions how to diagnose/fix this?

Answer

"hadley/ggplot2: plotting polygon shapefiles" says "..., the hole state is retained, but this information is not used by ggplot2". Fortunately, ggspatial package, "Fish & Whistle: Holes in ggplot polygons" taught me, seem to solve some problems, such as the overlapping problem. (The white area upper label of "Biggin Hill" isn't due to ggspatial package because it is on ggplot(d) + geom_polygon(aes(long, lat, group = group, fill = id)) on my env.

devtools::install_github("paleolimbot/ggspatial")

library(ggspatial)

ggmap(toner) + geom_spatial(data=v, aes(fill=id), alpha=.8)

enter image description here