I came up with a way to plot rivers using geom_path. I do not know if there is a better way. I had to split the dataframe into hundreds of "rivers". So it is very slow. Any ideas?
world_map <- map_data('world')
system("wget https://sites.google.com/site/joabelb/Home/PrincRiosBrazil.zip")
system("unzip -o PrincRiosBrazil.zip")
library(rgdal)
shapeHid <- readOGR(dsn = ".", layer = "PrincipaisRiosDoBrasil")
shapeHid@data$id = rownames(shapeHid@data)
library(ggplot2)
shapeHid.points = fortify(shapeHid, region="id")#
shapeHid.df = merge(shapeHid.points, shapeHid@data, by="id", all=F)
listofrivers<-split(shapeHid.df, shapeHid.df$id)
myMap3 <- ggplot() +
lapply(listofrivers, function(x) geom_path(data=x, aes(x=long, y=lat), color="gray70", linetype=1)) +
geom_map(data = world_map, map = world_map, aes(map_id = region),
color = 'black', fill = NA, linetype=2) +
theme(panel.border = element_rect(fill = NA, colour = "black"))+
theme(axis.title=element_blank())+
scale_y_continuous(limits=c(-15,6),expand=c(0,0))+
scale_x_continuous(limits=c(-76,-55),expand=c(0,0))
myMap3
If you routinely work with shapefiles, geom_path and geom_polygon gives everything you need. In recent versions, ggplot deals directly with spatial objects, so there's no need to use fortify and merge (probably the step taking more time in your code). Here's an example using the shapefile of federative units of Brazil from IBGE as base map:
shapeUFs <- readOGR('.', 'BRUFE250GC_SIR')
shapeHid <- readOGR('.', 'PrincipaisRiosDoBrasil')
ggplot(shapeUFs, aes(long, lat, group = group)) +
geom_polygon(fill = 'gray90', color = 'black') +
geom_path(data = shapeHid, color = 'steelblue2') +
coord_map() + theme_void()
Performance will be affected by the size of your shapes (determined by number of features and level of details) more than the geometry you're using in ggplot. You can use rgeos::gSimplify to reduce the number of vertices in a spatial polygon/lines object. You can also plot points directly over the map:
# Simplifying the geometry of the federative units
shapeUFs.s <- rgeos::gSimplify(shapeUFs, .05, TRUE)
# Storing map in an object
riversMap <- ggplot(shapeUFs.s, aes(long, lat)) +
geom_polygon(aes(group = group), fill = 'gray90', color = 'black') +
geom_path(data = shapeHid, aes(group = group), color = 'steelblue2') +
coord_map() + theme_void()
# Sampling 20 cities in Brazil
brMunics <- read.csv('https://raw.githubusercontent.com/kelvins/Municipios-Brasileiros/master/Municipios_Brasileiros.csv')
Munics <- brMunics[sample(nrow(brMunics), 20), ]
# Plotting points over the map
riversMap + geom_point(data = Munics, aes(Longitude, Latitude), color = 'red')
# If your data already have the coordinates named 'lat' and 'long',
# you can skip aes(Longitude, Latitude):
names(Munics)[6:7] <- c('lat','long')
riversMap + geom_point(data = Munics, color = 'red')
I would do the following:
library(sf)
library(ggplot2)
world_map <- map_data('world')
sdf <- read_sf("PrincipaisRiosDoBrasil.shp")
myMap3 <- ggplot() +
geom_map(data = world_map, map = world_map, aes(map_id = region), color = 'black', fill = NA, linetype=2) +
geom_sf(data = sdf)+
theme(panel.border = element_rect(fill = NA, colour = "black"))+
theme(axis.title=element_blank())+
scale_y_continuous(limits=c(-15,6),expand=c(0,0))+
scale_x_continuous(limits=c(-76,-55),expand=c(0,0))
myMap3
You'll need to update ggplot2 to 3.0.0 for geom_sf
.