In R I want to apply the Mercator-Projection to a SpatialPolygonsDataFrame before plotting it with ggplot. I dont want to use ggplot::coord_map() since the map is supposed to be the "canvas" for a network-graph, that i dont want to be mercator-projected aswell.

After using the sp::spTransform() function I was unable to broom::tidy() the resulting SpatialPolygonsDataFrame due to "orphaned holes"...

Is the SpatialPolygonsDataFrame provided by cshapes::cshp() somehow faulty or am I doing the transformation wrong?

PS: The cleangeo::clgeo_Clean()-function (Suggested here: Fixing orphaned holes in R) has been computing for at least 3 hours sofar. It doesn't seem to be the ideal approach - even if it turns out to be working...

> library(cshapes)
Loading required package: sp
Loading required package: maptools
Checking rgeos availability: TRUE
Loading required package: plyr

> library(broom)

> wrld <- 
+   cshp(as.Date("2016-01-01"))
Warning message:
use rgdal::readOGR or sf::st_read 

> class(wrld)
[1] "SpatialPolygonsDataFrame"
[1] "sp"

> proj4string(wrld)
[1] "+proj=longlat +ellps=WGS84"

> wrld <-
+   spTransform(wrld, CRS("+proj=merc +lon_0=0 +k=1 +x_0=0
+                          +y_0=0 +ellps=WGS84 +datum=WGS84
+                          +units=m +no_defs"))

> wrld <- 
+   broom::tidy(wrld, region="COWCODE")
Error in createPolygonsComment(p) : 
  rgeos_PolyCreateComment: orphaned hole, cannot find containing polygon for hole at index 84

The data is actually broken after spTransform - there's an ambiguity at longitude -180/180 that doesn't survive the Mercator transformation, presumably because the polygons are cut exactly at that line. Try a tiny negative buffer, ignore the "planar" warning from rgeos, we are doing this in the native crs which is entirely proper. The comment complaint is a real limitation of sp, but I don't think there are any holes to really matter in this data at this scale. There are better data sets for your purpose perhaps, and sf is better at the hole-definition-hierarchy.

wrld <-    cshp(as.Date("2016-01-01"))

wrld0 <- rgeos::gBuffer(wrld, width = -0.0001, byid = TRUE)

  sp::spTransform(wrld0, CRS("+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"))

You don't really need broom, it's just a copy of fortify that was intended to go further but has not afaik, mainly I think because sf now rules the roost (not sp).

tab <- ggplot2::fortify(wrld0, region = "COWCODE")
tab$COWCODE <- tab$id

ggplot(tab) + geom_polygon(aes(long, lat, group = group, fill = COWCODE)) + 
guides(fill = FALSE)

Finally, don't use Mercator if you can help it - there's likely a more suitable projection for your task.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.