How to draw ggmap with two different administrative boundaries? - r

I am wondering how to draw a map using get_map and ggmap of any federal country (i.e. a country with provinces and counties). Any country, other than the US would be great. To make it look nice, fill the geom_polygon of counties (any fill), and provinces are empty polygons, only with its contours. So, basically, it is two overlapping ggmaps.
You can get the shapefiles here:
https://www.dropbox.com/s/4nl685t860x1e8r/municipios_br.zip
rm(list = ls())
library(ggplot2)
library(rgdal)
library(ggmap)
# READ SHAPEFILE OF BOUNDARIES
Map <- readShapePoly("municipios_br.shp")
head(as.data.frame(Map))
Map = gBuffer(Map, width=0, byid=TRUE)
MapC <- fortify(Map, region="CODIGO_MUN") # municipalities
MapP <- fortify(Map, region="CODIGO_UF") # state boundaries
MapC$test <- 1
MapP$test <- 1
MapC <- Map[order(MapC$order),]
MapP <- MapP[order(MapP$order),]
The following code produces counties boundaries:
google.map <- get_map(location = 'Brazil', zoom=4,maptype="terrain")
m0 <- ggmap(google.map)
m1 <- m0 + geom_polygon(color = 'grey90', size = .01, aes(x=long, y=lat, group=group, fill=as.factor(test)), data=MapC, alpha=.6)
m1 + guides(fill=FALSE) + scale_fill_manual(values=c("red"))
Now, provinces:
m2 <- m0 + geom_polygon(color = 'grey50', size = .1, aes(x=long, y=lat, group=group, fill=as.factor(test)), data=MapP, alpha=.9)
m2 + guides(fill=FALSE) + scale_fill_manual(values=c(NA))
How to make the two work together?

You could also get your maps from e.g. GADM:
library(raster)
adm1 <- getData('GADM', country='HUN', level=0)
adm2 <- getData('GADM', country='HUN', level=1)
And let us fortify those for ggplot usage:
library(ggplot2)
fadm1 = fortify(adm1)
fadm2 = fortify(adm2)
And add as many layers and geoms as you wish:
ggplot(fadm1, aes(x = long, y = lat, group = group)) + geom_path() +
geom_polygon(data = fadm2, aes(x = long, y = lat),
fill = "green", alpha = 0.5) +
geom_path(data = fadm2, aes(x = long, y = lat), color = "blue") +
theme_bw()
Resulting in:
Update: combining your two layers mentioned in the updated questions
m0 + geom_polygon(size = .01,
aes(x = long, y = lat, group = group, fill = as.factor('red')),
data = MapC,
alpha = .6) +
geom_path(color = 'grey50', size = .1, aes(x = long, y = lat, group = group),
data=MapP, alpha=.9) +
guides(fill=FALSE)

Related

Representing different layers in a ggplot map! R

M intention is to represent 3 different layers of information in a ggplot map:
1. The map itself using a MULTIPOLYGON file
2. Kriging estimations using geom_tile()
3. datapoints using geom_point()
I used the following script:
library(rnaturalearth)
library(rnaturalearthdata)
world <- ne_countries(scale = "medium", returnclass = "sf")
windows()
ggplot(data = world) +
geom_sf(color="black",fill="grey90") +
theme(panel.background = element_blank()) +
coord_sf(xlim = c(-12.3, 95), ylim = c(70, 22), expand = FALSE) +
geom_tile(data = myKrige, aes(x= x1, y= x2, fill =var1.pred)) +
geom_point(data = roh, aes(x = LON, y = LAT))
In this script I used three datasets: world (a MULTIPOLYGON obtained from rnaturalearthdata), myKrige (data frame obtained from a spatialPointsDataFrame) and roh (data frame with latitude and longitude data points).
This is the figure my script produces:
As you can see the different layers are on top of each other. But I would like to merge nicely the geom_tile with the base plot.
Any idea how can I do it easily. Or should I rethink the complete figure?
Here is starting point, following an example from https://rpubs.com/nabilabd/118172
library(rnaturalearth)
library(rnaturalearthdata)
library(ggplot2)
library(sf)
world <- ne_countries(scale = "medium", returnclass = "sf")
df <- data.frame(x=rnorm(10,sd = 3),
y=rnorm(10,sd = 3))
df <- sf::st_as_sf(df, coords=c("x","y"), crs = 4326, agr = "constant", remove = F)
ggplot(data = world) +
geom_sf() +
geom_sf(data=df) +
# The idea would then to add add a scale_fill_gradient() such
# as in https://rpubs.com/nabilabd/118172 , but I dont know
# how the kring data should look like.
coord_sf(xlim = c(-10,10), ylim=c(-10,10))
# example
lzn.kriged %>% as.data.frame %>%
ggplot(aes(x=x, y=y)) + geom_tile(aes(fill=var1.pred)) + coord_equal() +
scale_fill_gradient(low = "yellow", high="red") +
scale_x_continuous(labels=comma) + scale_y_continuous(labels=comma) +
theme_bw()

Plotting Illinois with ggmap and ggplot in r

I am trying to plot out a base map of Illinois by counties.
Libraries I had loaded:
library(ggplot2)
library(maps)
library(ggmap)
library(mapdata)
This is my code:
states <- map_data("state")
IL <- subset(states, region %in% c("illinois"))
counties <- map_data("county")
IL_county <- subset(counties, region == "illinois")
il_base <- ggplot(data = IL, mapping = aes(x = long, y = lat)) +
coord_fixed(1.3) +
geom_polygon(color = "black", fill = NA) +
theme_nothing()
il_base
il_base +
geom_polygon(data = IL_county, fill = NA, color = "black") +
geom_polygon(color = "black", fill = NA)
The il_base plot is fine, it shows a basic outline of the state. However, as soon as I add geom_polygon to this it maps the counties out like this:
And this is NOT what the counties of IL look like. What did I do wrong here?
I solved the problem by modifying the base plot to:
# Add group
il_base <- ggplot(data = IL, mapping = aes(x = long, y = lat, group = group)) +
coord_fixed(1.3) +
geom_polygon(color = "black", fill = NA) +
theme_nothing()

how to plot rivers efficiently?

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.

Labelling points on world map in ggplot2 [duplicate]

This question already has answers here:
Show the value of a geom_point using geom_text
(2 answers)
Closed 5 years ago.
I have created a world map with the use of the ggplot2 library.
I am attempting to label the two cities (Shanghai and Sao Paulo) respectively through using labels in ggplot2. However, when I try to add labels I get the error message:
Warning: Ignoring unknown aesthetics: labels
Error: geom_text requires the following missing aesthetics: x, y, label
Here is the full code:
require(maps)
require(mapdata)
library(ggplot2)
countries = c("Sao Paulo","Shanghai")
global <- map_data("world")
ggplot() + geom_polygon(data = global, aes(x=long, y = lat, group =
group)) +
coord_fixed(1.3)
ggplot() +
geom_polygon(data = global, aes(x=long, y = lat, group = group),
fill = NA, color = "red") +
coord_fixed(1.3)
gg1 <- ggplot() +
geom_polygon(data = global, aes(x=long, y = lat, group = group),
fill = "green", color = "blue") +
coord_fixed(1.3)
gg1
labs <- data.frame(
long = c(-46.625290,121.4580600),
lat = c(-23.533773,31.2222200),
stringsAsFactors = FALSE
)
gg1 +
geom_point(data = labs, aes(x = long, y = lat), color = "red", size
= 5) + ggtitle("World Map") + geom_text(aes(labels=countries),vjust=0,
colour="red")
Clearly, I'm using ggplot wrong in some way but can't figure out how.
labs$countries <- countries
gg1 +
geom_point(data=labs, aes(long, lat), colour="red", size=5) +
ggtitle("World Map") +
geom_text(data=labs, aes(long, lat, label=countries))

Administrative regions map of a country with ggmap and ggplot2

I can make USA state level unemployment graph with the following code.
library(XML)
library(ggplot2)
library(plyr)
library(maps)
unemp <-
readHTMLTable('http://www.bls.gov/web/laus/laumstrk.htm',
colClasses = c('character', 'character', 'numeric'))[[2]]
names(unemp) <- c('rank', 'region', 'rate')
unemp$region <- tolower(unemp$region)
us_state_map <- map_data('state')
map_data <- merge(unemp, us_state_map, by = 'region')
map_data <- arrange(map_data, order)
states <- data.frame(state.center, state.abb)
p1 <- ggplot(data = map_data, aes(x = long, y = lat, group = group))
p1 <- p1 + geom_polygon(aes(fill = cut_number(rate, 5)))
p1 <- p1 + geom_path(colour = 'gray', linestyle = 2)
p1 <- p1 + scale_fill_brewer('Unemployment Rate (Jan 2011)', palette = 'PuRd')
p1 <- p1 + coord_map()
p1 <- p1 + geom_text(data = states, aes(x = x, y = y, label = state.abb, group = NULL), size = 2)
p1 <- p1 + theme_bw()
p1
Now I want to similar kind of graph for Pakistan. My few attempts results are below:
data(world.cities)
Pakistan <- data.frame(map("world", "Pakistan", plot=FALSE)[c("x","y")])
p <- ggplot(Pakistan, aes(x=x, y=y)) +
geom_path(colour = 'green', linestyle = 2) +
coord_map() + theme_bw()
p <- p + labs(x=" ", y=" ")
p <- p + theme(panel.grid.minor=element_blank(), panel.grid.major=element_blank())
p <- p + theme(axis.ticks = element_blank(), axis.text.x = element_blank(), axis.text.y = element_blank())
p <- p + theme(panel.border = element_blank())
print(p)
and
library(mapproj)
Country <- "Pakistan"
Get_Map_Country <-
get_map(
location = Country
, zoom = 5
, scale = "auto"
, maptype = "roadmap"
, messaging = FALSE
, urlonly = FALSE
, filename = "ggmapTemp"
, crop = TRUE
, color = "color"
, source = "google"
, api_key
)
Country1 <-
ggmap(
ggmap = Get_Map_Country
, extent = "panel"
# , base_layer
, maprange = FALSE
, legend = "right"
, padding = 0.02
, darken = c(0, "black")
)
Country1 <- Country1 + labs(x="Longitude", y="Latitude")
print(Country1)
Country2 <- Country1 + geom_polygon(data = Pakistan
, aes(x=x, y=y)
, color = 'white', alpha = .75, size = .2)
print(Country2)
Questions
I wonder how to get map of administrative regions of Pakistan as of USA. I know for this we need longitude and latitude of administrative boundaries. I'm wondering how to get longitude and latitude of administrative boundaries for a country. I tried Global Administrative Areas but without success.
I don't know the spatial level of administrative areas you require, but here's two ways
to read in shapefile data and .RData formats from Global Administrative Areas (gadm.org), and converting them into data frames for use in ggplot2. Also, in order to replicate the U.S. map, you will need to plot the administrative area names located at the polygon centroids.
library(ggplot2)
library(rgdal)
Method 1. SpatialPolygonDataFrames stored as .RData format
# Data from the Global Administrative Areas
# 1) Read in administrative area level 2 data
load("/Users/jmuirhead/Downloads/PAK_adm2.RData")
pakistan.adm2.spdf <- get("gadm")
Method2. Shapefile format read in with rgdal::readOGR
pakistan.adm2.spdf <- readOGR("/Users/jmuirhead/Downloads/PAK_adm", "PAK_adm2",
verbose = TRUE, stringsAsFactors = FALSE)
Creating a data.frame from the spatialPolygonDataframes and merging with a data.frame containing the information on unemployment, for example.
pakistan.adm2.df <- fortify(pakistan.adm2.spdf, region = "NAME_2")
# Sample dataframe of unemployment info
unemployment.df <- data.frame(id= unique(pakistan.adm2.df[,'id']),
unemployment = runif(n = length(unique(pakistan.adm2.df[,'id'])), min = 0, max = 25))
pakistan.adm2.df <- merge(pakistan.adm2.df, unemployment.df, by.y = 'id', all.x = TRUE)
Extracting names and centoids of administrative areas for plotting
# Get centroids of spatialPolygonDataFrame and convert to dataframe
# for use in plotting area names.
pakistan.adm2.centroids.df <- data.frame(long = coordinates(pakistan.adm2.spdf)[, 1],
lat = coordinates(pakistan.adm2.spdf)[, 2])
# Get names and id numbers corresponding to administrative areas
pakistan.adm2.centroids.df[, 'ID_2'] <- pakistan.adm2.spdf#data[,'ID_2']
pakistan.adm2.centroids.df[, 'NAME_2'] <- pakistan.adm2.spdf#data[,'NAME_2']
Create ggplot with labels for administrative areas
p <- ggplot(pakistan.adm2.df, aes(x = long, y = lat, group = group)) + geom_polygon(aes(fill = cut(unemployment,5))) +
geom_text(data = pakistan.adm2.centroids.df, aes(label = NAME_2, x = long, y = lat, group = NAME_2), size = 3) +
labs(x=" ", y=" ") +
theme_bw() + scale_fill_brewer('Unemployment Rate (Jan 2011)', palette = 'PuRd') +
coord_map() +
theme(panel.grid.minor=element_blank(), panel.grid.major=element_blank()) +
theme(axis.ticks = element_blank(), axis.text.x = element_blank(), axis.text.y = element_blank()) +
theme(panel.border = element_blank())
print(p)
Have you tried http://www.diva-gis.org/gdata? That should give you Shapefiles with state/district boundaries for Pakistan.
The maptools package has functions that let you read and convert Shapefiles to a dataframe that can be used to lay out the boundary polygons.

Resources