2

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"
attr(,"package")
[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
Vince
  • 20,017
  • 15
  • 45
  • 64

1 Answers1

3

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.

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

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

plot(
  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

library(ggplot2)
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.

mdsumner
  • 8,196
  • 1
  • 27
  • 30