Developing Geographic Thematic Maps with R - r

There are clearly a number of packages in R for all sorts of spatial analysis. That can by seen in the CRAN Task View: Analysis of Spatial Data. These packages are numerous and diverse, but all I want to do is some simple thematic maps. I have data with county and state FIPS codes and I have ESRI shape files of county and state boundaries and the accompanying FIPS codes which allows joining with the data. The shape files could be easily converted to other formats, if needed.
So what's the most straight forward way to create thematic maps with R?
This map looks like it was created with an ESRI Arc product, but this is the type of thing I would like to do with R:
alt text http://www.infousagov.com/images/choro.jpg Map copied from here.

The following code has served me well. Customize it a little and you are done.
(source: eduardoleoni.com)
library(maptools)
substitute your shapefiles here
state.map <- readShapeSpatial("BRASIL.shp")
counties.map <- readShapeSpatial("55mu2500gsd.shp")
## this is the variable we will be plotting
counties.map#data$noise <- rnorm(nrow(counties.map#data))
heatmap function
plot.heat <- function(counties.map,state.map,z,title=NULL,breaks=NULL,reverse=FALSE,cex.legend=1,bw=.2,col.vec=NULL,plot.legend=TRUE) {
##Break down the value variable
if (is.null(breaks)) {
breaks=
seq(
floor(min(counties.map#data[,z],na.rm=TRUE)*10)/10
,
ceiling(max(counties.map#data[,z],na.rm=TRUE)*10)/10
,.1)
}
counties.map#data$zCat <- cut(counties.map#data[,z],breaks,include.lowest=TRUE)
cutpoints <- levels(counties.map#data$zCat)
if (is.null(col.vec)) col.vec <- heat.colors(length(levels(counties.map#data$zCat)))
if (reverse) {
cutpointsColors <- rev(col.vec)
} else {
cutpointsColors <- col.vec
}
levels(counties.map#data$zCat) <- cutpointsColors
plot(counties.map,border=gray(.8), lwd=bw,axes = FALSE, las = 1,col=as.character(counties.map#data$zCat))
if (!is.null(state.map)) {
plot(state.map,add=TRUE,lwd=1)
}
##with(counties.map.c,text(x,y,name,cex=0.75))
if (plot.legend) legend("bottomleft", cutpoints, fill = cutpointsColors,bty="n",title=title,cex=cex.legend)
##title("Cartogram")
}
plot it
plot.heat(counties.map,state.map,z="noise",breaks=c(-Inf,-2,-1,0,1,2,Inf))

Thought I would add some new information here since there has been some activity around this topic since the posting. Here are two great links to "Choropleth Map R Challenge" on the Revolutions blog:
Choropleth Map R Challenge
Choropleth Challenge Results
Hopefully these are useful for people viewing this question.
All the best,
Jay

Check out the packages
library(sp)
library(rgdal)
which are nice for geodata, and
library(RColorBrewer)
is useful for colouring. This map is made with the above packages and this code:
VegMap <- readOGR(".", "VegMapFile")
Veg9<-brewer.pal(9,'Set2')
spplot(VegMap, "Veg", col.regions=Veg9,
+at=c(0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5),
+main='Vegetation map')
"VegMapFile" is a shapefile and "Veg" is the variable displayed. Can probably be done better with a little work. I don`t seem to be allowed to upload image, here is an link to the image:

Take a look at the PBSmapping package (see borh the vignette/manual and the demo) and
this O'Reilly Data Mashups in R article (unfortunately it is not free of charge but it worth 4.99$ to download, according Revolutions blog ).

It is just three lines!
library(maps);
colors = floor(runif(63)*657);
map("state", col = colors, fill = T, resolution = 0)
Done!!
Just change the second line to any vector of 63 elements (each element between 0 and 657, which are members of colors())
Now if you want to get fancy you can write:
library(maps);
library(mapproj);
colors = floor(runif(63)*657);
map("state", col = colors, fill = T, projection = "polyconic", resolution = 0);
The 63 elements represent the 63 regions whose names you can get by running:
map("state")$names;

The R Graphics Gallery has a very similar map which should make for a good starting point. The code is here: www.ai.rug.nl/~hedderik/R/US2004 . You'd need to add a legend with the legend() function.

If you stumble upon this question in the 2020ies, use the magnificent tmap package. It's very simple and straightforward and revolutionized making maps in R. Do not bother to investigate this complicated code.
Check the vignette here.

Related

Unable to create a multilinestring using st_intersection that is good enough to use border_segment from the SpatialRDD package

I’ve been following the following tutorial https://axlehner.github.io/SpatialRDD/articles/spatialrdd_vignette.html#assign-treatment for SpatialRDD using my own dataset and maps. I’ve run into a problem when attempting to use border_segment. In the tutorial the author has a cut off line he uses which describes a spatial discontinuity. In my own project I am trying to create such a cut off line using historical boundaries and by taking the intersection. I’ve been using two neighboring polygons and taking the intersection of their boundaries using st_intersection to create this cut off. However, once I reach the point where I need to use border_segment it does not work as intended.
If for instance I want 2 border segments to be created using my region, points in that region, and my cut off line, it appears border_segment creates 2 segments for each line segment of my cut off line (the cut off line I created using the intersection of boundaries). Furthermore, comparing the cut off line from the tutorial (can be loaded into R using SpatialRDD::data("cut_off.sf")) to the one I create, the one in the tutorial has one big matrix describing the geometry, while the one I create is described by many 2x2 matrices. I think this is where the problem might be stemming from, but I have no idea how to fix it. I think by finding a solution it would help to understand how to create better geographical objects using just R.
I’ve created a reproducible example to illustrate the issue:
library(SpatialRDD)
library(sf)
library(tmap)
library(spData) #loading various maps
#getting worldmap
data("world")
#changing to a localised projection system
world <- st_transform(world, "EPSG:3035")
#getting just Germany
germany <- world[world$name_long == "Germany",]
#getting just Poland
poland <- world[world$name_long == "Poland",]
#taking the union of Germany and Poland to later distribute random points in them
union <- st_union(germany, poland)
#taking the intersection of their borders, which will act as a cut off line
cut_off <- st_intersection(germany, poland)
#creating random points for exercise to work (similar code to what is done in tutorial)
set.seed(1088) # set a seed
points_samp <- sf::st_sample(union, 1000)
points_samp <- sf::st_sf(points_samp) # make it an sf object
#using border_segment to sort points into 2 border regions
points_samp$segment2 <- border_segment(points_samp, cut_off, 2)
#mapping the points in their respective border segments
tm_shape(points_samp) + tm_dots("segment2", size = 0.1) + tm_shape(cut_off) + tm_lines()
As you will see when plotting the points after creating the border segments, that there will be many border segments even though I indicated for border_segment to create only two.
I’m fairly new to R and geospatial manipulation, so maybe there is a simple solution, but I’ve searched everywhere and haven’t been able to find one. This is the first time after using stack overflow for years that I’ve had to actually post. Please let me know if you need any other information or if I was not clear enough at some point!

How to draw a state map using R

I need help on how to use R to draw a map. I have created an excel csv file with latitude and longitude of counties at the boundaries of the state I want to draw. However, I don’t know the right codes in R to use and get the map drawn.
#R #Maps #howtodrawmapsinR #ggplot2 #Rmapcodes
As simple as:
library(maps)
map('county', 'iowa', fill = TRUE, col = palette())
If you like to use the data from your .csv file, then please have a look on sf and sp libraries and get familiar with creating simple geometries, like SpatialPolygons.

Create Tesselation from SpatialPolygonsDataFrame?

Novice R programmer here... Looking for guidance on building a tess out of the polygons in a SpatialPolygonsDataFrame.
I am invoking quadratcount on points within a state boundary. Rather than using the default grid, I would like to use custom polygons to define the quadrats. Specifically, the county polygons which I have in shapefile format.
I take it from the documentation that the desired tesselation can be created out of a list of 'owin' objects. Where I'm getting jammed up is in taking my SpatialPolygonsDataFrame to generate that list.
I have confirmed that the polygons are read in correctly:
counties <- readOGR('/path/to/counties.shp', layer = "CountyBoundaries", GDAL1_integer64_policy = FALSE)
for(i in 1:nrow(counties)) {
plot(counties[i,])
}
Which generates a series of plots, one per county. That is, of course, only useful to know that my data isn't broken and that I can iterate over the polygons. What I think I need to do is make an owin out of each polygon in the SpatialPolygonsDataFrame and append that to myList for tess(tiles=myList). Not having much success in that approach.
My strong suspicion is that there's an easier way...
Many Thanks,
--gt
Turns out my problem was in not fully understanding how lists are indexed in R. The following bit of code gives me the result I want.
I have no doubt that there is a better, vectorized, way to do it. But in the mean while:
# The point events are in a PPP: StateCrimes_ppp
counties <- readOGR('/path/to/counties.shp', layer = "CountyBoundaries", GDAL1_integer64_policy = FALSE)
tlist <- list()
for(i in 1:nrow(counties)) {
tlist[[i]] <- as(counties[i,], 'owin')
}
QuadCount <- quadratcount(
StateCrimes_ppp,
tess=tess(tiles=tlist)
)
plot(QuadCount, main=NULL)
plot(intensity(QuadCount, image=TRUE), main=NULL, las=1)
If anybody sees how I've taken the long and hard way to solve a simple problem, I'd love to know a better, simpler, more elegant, or more R-like way to do this.
Thanks again,
--gt

Convert Spatial Lines to Spatial Polygons

Is there an easy way to convert a Spatial Lines into a Spatial Polygon object within R?
Reproducible Example
I have put together a reusable dataset here, which is downloaded from OpenStreetMaps through the overpass package. This extracts the locations of a few airports in South England:
devtools::install_github("hrbrmstr/overpass")
library(overpass)
library(raster)
library(sp)
# Write Query
query_airport <- '
(node["aeroway"="aerodrome"](50.8, -1.6,51.1, -1.1);
way["aeroway"="aerodrome"](50.8, -1.6,51.1, -1.1);
relation["aeroway"="aerodrome"](50.8, -1.6,51.1, -1.1);
);
out body;
>;
out skel qt;
'
# Run query
shp_airports <- overpass::overpass_query(query_airport, quiet = TRUE)
crs(shp_airports) <- CRS("+init=epsg:4326") # Add coordinates
shp_airports <- shp_airports[,1]
# Plot Results
plot(shp_airports, axes = T)
However, the data is of the class "SpatialLinesDataFrame". This really messes things up if you want to do any form of spatial joins or intersections, as it only acknowledges the edge of the region.
Potential Leads
I was exploring the use of SpatialLines2PolySet within the maptools package, but in my time exploring I produced nothing but error codes, so I didn't think there would be any worth including these within the question. There is some guidance about these functions here: https://rdrr.io/rforge/maptools/man/SpatialLines2PolySet.html
Notes
I have searched the web and SO to see find similar questions and struggled to find any questions directly referring to this. A lot seem to reference converting SpatialPoints -> SpatialLineDataFrames , but not SpatialLineDataFrames -> SpatialPolygonDataFrames. This question is similar but lacks any answers (or a reproducible dataset): Close a spatial line into a polygon using a shapefile
In addition, it seems strange that this would be difficult as it is something which can be done so easily in ArcGIS using the "Feature to Polygon" tool. This function requires no additional arguments specified and it works perfectly.
A way to solve the problem would be to use the library sf. After your query
library(sp)
library(raster)
library(sf)
sf_airports <- st_as_sf(shp_airports)
sf_airports_polygons <- st_polygonize(sf_airports)
shp_airports <- as(sf_airports_polygons, "Spatial") # If you want sp
class(shp_airports)

making a choropleth from SpatialPolygonsDataFrame- ggplot vs ggplot2 vs plot?

I have a shapefile, specifically, a SpatialPolygonsDataFrame, called cdtract. that contains one variable for each district called varcount. varcount is either "NA" or 1. When I do
plot(cdtract)
...I see the map printed out but I don't see the tracts that are '1' in varcount marked any differently from those that are 'NA.' I ideally want to have a spectrum of values in varcount and see those reflected in different colors. I considered using ggplot but according to this post here that is very resource intensive and it might be better to use plot() instead of ggplot() to create the choropleth. But I'm really not sure how to go about it. I am using a different shapefile from states/countries so am not sure that the choroplethr package is the way to go.
Can someone explain how to take a SpatialPolygonsDataFrame and turn it into a choropleth, efficiently? Thanks!
Shamefully taken from Ari's post on gis.stackexchange.com. See the link for pictures. There are more examples here.
library(sp)
Srs1 = Polygons(list(Polygon(cbind(c(2,4,4,1,2),c(2,3,5,4,2)))), "s1")
Srs2 = Polygons(list(Polygon(cbind(c(5,4,2,5),c(2,3,2,2)))), "s2")
SpDF <- SpatialPolygonsDataFrame( SpatialPolygons(list(Srs1,Srs2)),
data.frame(z=1:2, row.names=c("s1","s2") ) )
spplot(SpDF, zcol="z")

Resources