Great circles, raster, sp and lattice
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Recently I found a post at FlowingData with a detailed tutorial to map connections with great circles with R. The tutorial of FlowingData is excellent, but I feel more comfortable with the sp classes and methods, and with the lattice and latticeExtra packages. Besides, I want to use the free spatial data available from the DIVA-GIS project, from the developer of the raster and the geosphere packages.
Here is what I have got.
First, let’s load the packages.
library(lattice) library(latticeExtra) library(maps) library(geosphere) library(sp) library(maptools) library(raster)
Now it’s time to get the data. First, airports and flights:
airports <- read.csv("http://datasets.flowingdata.com/tuts/maparcs/airports.csv", header=TRUE) flights <- read.csv("http://datasets.flowingdata.com/tuts/maparcs/flights.csv", header=TRUE, as.is=TRUE)
With this information, following the code from the FlowingData post, let’s define a list of SpatialLines. The makeLines function defines a SpatialLines for each connection, and stores the number of flights in the ID slot. The linesAA is a list with the result of makeLines over fsub with the apply function. Previously, the fsub data.frame has been ordered by cnt, as the FlowingData post teaches.
makeLines <- function(x){ air1 <- airports[airports$iata == x[2],]##start air2 <- airports[airports$iata == x[3],]##end inter <- gcIntermediate(c(air1[1,]$long, air1[1,]$lat), c(air2[1,]$long, air2[1,]$lat), n=100, sp=TRUE, addStartEnd=TRUE) inter@lines[[1]]@ID <- as.character(x[4])##cnt inter } fsub <- flights[flights$airline == "AA",] fsub <- fsub[order(fsub$cnt),] linesAA <- apply(fsub, 1, makeLines)
Each component of the list can be plot with the sp.lines function. The colIndex function assigns a color from a palette to the values of cnt stored in the ID slot.
colIndex <- function(x, cnt, palette)palette[match(x, cnt)] makePlot <- function(x, cnt, palette){ idx <- as.numeric(x@lines[[1]]@ID) sp.lines(x, col.line=colIndex(idx, cnt, palette)) }
I define the palette for the list of lines with a combination of colorRampPalette, brewer.pal and level.colors, following the example of the help file of this last function.
cnt <- fsub$cnt breaks <- do.breaks(range(cnt), 30) palLines <- colorRampPalette(brewer.pal('Greens', n=9)) colors <-level.colors(cnt, at = breaks, col.regions = palLines)
Let’s get the elevation data. You have to download and unzip this file (you can use the getData function from the raster package, but I am having problems with it.). The next code builds a sp object with this information:
elevUSA <- raster('USA_alt/USA1_msk_alt.grd') prj <- CRS("+proj=longlat +datum=WGS84") projection(elevUSA) <- prj elevUSAsp <- as(sampleRegular(elevUSA, 5e5, asRaster=TRUE), 'SpatialGridDataFrame')
The altitude map is constructed with the spplot function over elevUSAsp. I use the combination of colorRampPalette and brewer.pal to get the palette.
palMap=colorRampPalette(brewer.pal('Greys', n=9)) altitudeMap <- spplot(elevUSAsp, col.regions=palMap, colorkey=list(space='bottom'), scales=list(draw=TRUE) )
Finally, the boundaries. You have to download and unzip this file.
mapUSA <- readShapeLines('USA_adm/USA_adm0.shp', proj4string=prj)
Now it’s time for joining all together. I use the layer function from latticeExtra to draw the boundaries (with sp.lines) and the list of lines (with lapply and makePlot).
p <- altitudeMap + layer(sp.lines(mapUSA, col.line='black')) + layer(lapply(linesAA, makePlot, cnt, colors))
Here it is! (click on the image for a high resolution PDF file)
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.