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.
Related
I am trying to incorporate labels of provinces, and cities with labels and dots into a South African map.I can get a map with provincial subdivisions from a spdf file, from website https://gadm.org/download_country_v3.html
SA1spdf <- readRDS("gadm36_ZAF_1_sp.rds")
And I am trying to use the information in the slot:
SA1spdf#data#ADM1_EN
that contains the label of the 9 provinces
I want to place the labels in the center of the polygons, if possible, so I got the centroids of the 9 provinces:
centroids_SAdf <- as.data.frame(coordinates(SA1spdf))
and change names V1 and V2 to Longitude and Latitude
names(centroids_SAdf) <- c("Longitude", "Latitude")
Also I want to add a few cities to the plot:
coordinates_cities <- data.frame(city = c("Cape Town", "Durban", "Johannesburg", "Port Elizabeth"),lat = c(-33.930, -29.870, -26.190, -33.960 ), lon = c(18.460, 30.990, 28.040,25.590 )
but I cannot link all these together.
I can get a map with:
qtm(SA1spdf, fill = "white")
Using maptools and the following codes all return error messages
qtm(SA1spdf, fill = "white") + tm_text("SA1spdf$data#ADMN1_EN")
tm_shape(SA1spdf) + tm_polygons() + tm_fill(col = "white")
I dont get a white filled map, its filled with grey colour
the following codes return error messages:
tm_shape(SA1spdf) + tm_polygons() + tm_text(c("Eastern Cape","Free State" , "Gauteng","KwaZulu-Natal", "Limpopo","Mpumalanga","North West","Nothern Cape","Western Cape"))
ggplot(SA1spdf, aes(x = lon, y = lat), group = group) + geom_polygon(fill = "white") + geom_point(data = coordinates_cities, aes(x = lat, y = lon)) + geom_text(data= coordinate_cities, aes(label = city))
library(sp)
library(ggplot2)
library(tmap)
library(rgeos)
I'll use the same object SA1spdf you created with data from ZAF as sp object from GADM
coordinate_cities <- data.frame(
city = c("Cape Town", "Durban", "Johannesburg", "Port Elizabeth"),
lat = c(-33.930, -29.870, -26.190, -33.960),
long = c(18.460, 30.990, 28.040,25.590))
base plot
plot(SA1spdf)
points(coordinate_cities$lon, coordinate_cities$lat, pch = 16, col = "red", cex = 1)
text(coordinate_cities$lon, coordinate_cities$lat, coordinate_cities$city, adj = c(0, 0), cex = 0.7)
title(main = "South Africa", sub = "Main cities")
ggplot2
sa_df <- fortify(SA1spdf)
#> Regions defined for each Polygons
ggplot(sa_df, aes(long, lat)) +
geom_polygon(aes(group = group), fill = "white", colour = "black") +
geom_point(data = coordinate_cities, aes(x = long, y = lat), colour = "red") +
geom_text(data = coordinate_cities, aes(label = city), vjust = -1) +
coord_equal()
tmap
# convert coordinate_cities to sp object
sa_cities_spdf <- SpatialPointsDataFrame(coords = coordinate_cities[, c("long", "lat")],
data = coordinate_cities[, "city", drop = FALSE],
proj4string = CRS("+proj=longlat +datum=WGS84"))
tm_shape(SA1spdf) +
tm_borders() +
tm_layout(main.title = "South Africa regions") +
tm_text("NAME_1", size = 0.7) +
tm_shape(sa_cities_spdf) + tm_symbols(size = 0.5, col = "red")
Created on 2021-06-17 by the reprex package (v0.3.0)
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.
I am trying to add US cities to my map in R.
When I add world cities:
ggplot(data = usa) +
geom_polygon(aes(x = longitude, y = latitude, group = group, fill = id)) +
coord_quickmap() +
guides(fill = FALSE) +
theme(axis.text = element_blank()) +
theme(axis.ticks = element_blank()) +
theme(axis.title = element_blank()) +
xlim(-169, -67) +
ylim(17,72)+
scale_fill_discrete()+
geom_point(data=world.cities, aes(x=long, y = lat, size= capital))
or canada cities:
ggplot(data = usa) +
geom_polygon(aes(x = longitude, y = latitude, group = group, fill = id)) +
coord_quickmap() +
guides(fill = FALSE) +
theme(axis.text = element_blank()) +
theme(axis.ticks = element_blank()) +
theme(axis.title = element_blank()) +
xlim(-169, -67) +
ylim(17,72)+
scale_fill_discrete()+
geom_point(data=canada.cities, aes(x=long, y = lat, size= capital))
it works just fine. However, when I try replacing it with us.cities, which is supposed to be part of the maps package (https://cran.r-project.org/web/packages/maps/maps.pdf), it gives the error:
ggplot2 doesn't know how to deal with data of class character.
any ideas on what could be the issue??
edit: more code:
library(maps)
library(fiftystater)
usa <- data("fifty_states")
us.cities <- data(us.cities)
usa.cities <- world.cities %>% filter(country.etc=="USA")
map <- map_data("world")
hawaii <- read.csv("hawaii.csv", stringsAsFactors = FALSE)
alaska <- read.csv("alaska.csv", stringsAsFactors = FALSE)
forty8states <- fifty_states %>% filter(id != "hawaii") %>% filter(id !="alaska") %>% select(long, lat, id, group)
alaska <- read.csv("alaska.csv", stringsAsFactors = FALSE)
hawaii <- read.csv("hawaii.csv", stringsAsFactors = FALSE)
usa <- rbind(forty8states, alaska, hawaii)
usa <- usa %>% mutate(longitude = round(long, digits = 2))
usa <- usa %>% mutate(latitude = round(lat, digits = 2))
the hawaii and alaska csv's are the hawaii and alaska data from the world data frame from maps, with some editing so they're in the same format as the rest.
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)
I am creating a choropleth county map with grey borders, and I also want to include the state boundries in black. Does anyone know how I go about adding a second layer of state mapping to an existing county map?
Here's the data set and code I ended up using:
#load libraries
library(ggplot2)
library(ggmap)
library(maps)
library(plyr)
#get wif file
wip <- read.csv("wip.csv")
#get map data for US counties and states
county_map <- map_data("county")
state_map <- map_data("state")
#merge wip and county_map
wip_map <- merge(county_map, wip, by.x=c("region", "subregion"),
by.y=c("region","subregion"), all.x=TRUE)
#resort merged data
wip_map <- arrange(wip_map, group, order)
#relpace NA with 0's
wip_map[is.na(wip_map)] <- 0
#generate a disctrete color pallette
pal <- c("#F7FCF5","#74C476","#41AB5D","#238B45","#006D2C","#00441B")
theme_clean <- function(base_size = 12) {
require(grid)
theme_grey(base_size) %+replace%
theme(
axis.title = element_blank(),
axis.text = element_blank(),
panel.background = element_blank(),
panel.grid = element_blank(),
axis.ticks.length = unit(0,"cm"),
axis.ticks.margin = unit(0,"cm"),
panel.margin = unit(0,"lines"),
plot.margin = unit(c(0,0,0,0),"lines"),
complete = TRUE
)
}
final_map <- ggplot(wip_map, aes(x=long, y=lat, group=group, fill=factor(CATEGORY))) +
geom_polygon(colour="grey", aes(fill=factor(CATEGORY))) +
scale_fill_manual(values=pal) +
expand_limits(x = wip_map$long, y = wip_map$lat) +
coord_map("polyconic") +
labs(fill="Number Per\nCounty") +
theme_clean()
final_map + geom_path( data = state_map , colour = "red")
Thanks!
Just add a geom_path to your code...
I used red to highlight the boundaries but you can easily just set it to black.
ggplot( wip_map, aes( x = long , y = lat , group=group ) ) +
geom_polygon( colour = "grey" , aes( fill = factor( CATEGORY ) ) ) +
scale_fill_manual( values = pal ) +
expand_limits( x = wip_map$long, y = wip_map$lat ) +
coord_map( "polyconic" ) +
labs(fill="Number Per\nCounty") +
theme_clean( ) +
geom_path( data = state_map , colour = "red")