Reputation: 63
I've problem with projecting properly map of Europe when I use coord_map
in ggplot
package. The code below gives me a weird and unwanted horizontal lines in random places. Does anyone know how to overcome this problem?
I don't want to use coord_quickmap
nor coord_cartesian
because I want to preserve straight lines of countries.
library(ggplot2)
map.world <- map_data("world")
ggplot(map.world, aes(x = long, y = lat)) +
geom_polygon(mapping = aes(x = long, y = lat, group = group), fill = "#B3B1B5", color = "#D9D8DA",size = 0.4) +
theme_minimal() +
theme(axis.text = element_blank(), text = element_blank(), panel.grid = element_blank()) +
coord_map(xlim = c(-27,36), ylim = c(34,67))
Upvotes: 3
Views: 1115
Reputation: 932
There are two ways to work around your problem:
The straightforward way
This way just needs a little tweaking of your code (note that I use magrittr's forward pipes):
library(maps)
library(magrittr)
library(maptools)
library(broom)
library(ggplot2)
europe <- maps::map("world", fill=TRUE, plot=FALSE) %>%
maptools::pruneMap(xlim = c(-27,36), ylim = c(34,67))
ggplot(data= broom::tidy(europe)) +
geom_polygon(mapping = aes(x = long, y = lat, group = group),
fill = "#B3B1B5", color = "#D9D8DA",size = 0.4) +
theme_void() +
coord_map()
The "owin/extent" approach
Another way to work around your problem can be done by using owin objects. This kind of objects will allow you to create a spatial window. Then you can represent only the intersection of such window over the world map.
Using this approach your code will be something as follows (also using magrittr's forward pipes and setting up a general CRS)
library(maps)
library(magrittr)
library(spatstat)
library(maptools)
library(raster)
library(broom)
library(ggplot2)
#Defining a general EPSG so there won't be any superposition problems
epsg <- "+proj=longlat +datum=WGS84 +no_defs"
#Using the original maps package, then converting map into SpatialPolygons object
map.world <- maps::map("world", fill=TRUE) %$%
maptools::map2SpatialPolygons(., IDs=names,proj4string=CRS(epsg))
#In order to keep the names of the countries we create the following data.frame
country.labs <- sapply(slot(map.world, "polygons"), function(x) slot(x, "ID")) %>%
data.frame( ID=1:length(map.world), name=., row.names = .)
#We convert object map.world into a SpatialPolygonsDataFrame object
map.world.SPDF <- sp::SpatialPolygonsDataFrame(map.world, country.labs)
#Creating owin object using your zooming coordinates
#This step always requires to load packages 'spatstat' and 'maptools'
zoom <- as(spatstat::as.owin(c(-27,36,34,67)), "SpatialPolygons")
raster::projection(zoom)=epsg
#Storing intersection between 'zoom' and 'world.map'
europe <- raster::intersect(map.world.SPDF, zoom)
#*country names of object europe can be accessed via europe@data
#Representing object 'europe' using broom::tidy to create a data.frame object
ggplot() +
geom_polygon(data = broom::tidy(europe, region="name"),
mapping = aes(x = long, y = lat, group = group),
fill = "#B3B1B5", color = "#D9D8DA",size = 0.4) +
theme_void() +
coord_map()
#*country names after tidying 'europe' this way are in a new column called 'id'
Depending on what you are doing, you may want to use
zoom <- as(raster::extent(c(-27,36,34,67)), "SpatialPolygons")
To create an extent object instead of an owin object (The result here is going to be the same)
The result obtained with any method is displayed below
In case you need to do different zooms you can easily wrap any of the alternatives up in a function.
I hope it helps
BONUS BALL: It might be interesting for you to check out the tmap package
Upvotes: 5