I am trying to make a Robinson-projection map that is not centered at longitude 0, and crosses both sides of the 180° line.
My code is below:
library("rnaturalearthdata")
world <- ne_countries(scale = "medium", returnclass = "sf")
robinson = "+proj=robin +lon_0=-90 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs"
transformed = st_transform(world, robinson)
ggplot(data=transformed) + geom_sf(fill = "gray", colour = "black")+theme_bw()
That generates this map, which is oriented correctly, except all the split boundaries are "inside out" and wrap across the whole map.
There is this related question from 9 years ago, but I am hoping that with recent package updates, there is a less complicated solution, which will allow us to plot our lat/lon data-points using geom_point()
without additional transformations.
EDIT #2: The solution by L. Tyrone works great for me. To plot points using this method, you will have to transform them from a data frame to an sf object with the same Coord Ref System, or else the lat/lon is interpreted as meters, and ends up indistinguishable from 0,0:
# Transform with fake data...
fakedata=data.frame(lat=c(-10,-20,80),lon=c(45,-100,120),tag=c("indian","tropical","arctic"))
transpoint = st_as_sf(fakedata,coords=c("lon","lat"),crs=4326)
dtran = st_transform(transpoint,robinson)
Then you can plot them by adding the special geometry=
and stat=
declarations to geom_point
or even geom_text_repel
:
geom_point(data=dtran,aes(geometry=geometry,color=tag),stat="sf_coordinates") +
geom_text_repel(data=dtran,aes(geometry=geometry,label=tag),stat="sf_coordinates")
You need to 'break' any polygons that cross 180 prior to projecting them. The st_break_antimeridian()
function from the sf
package is the easiest way to achieve this. It will throw a warning, which you can safely ignore.
library(rnaturalearth)
library(sf)
library(dplyr)
library(ggplot2)
world <- ne_countries(scale = "medium", returnclass = "sf") %>%
st_set_crs(4326)
robinson <- "+proj=robin +lon_0=-90 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"
world_robinson_90w <- world %>%
st_break_antimeridian(lon_0 = -90) %>%
st_transform(crs = robinson)
ggplot() +
geom_sf(data = world_robinson_90w)