Sometimes you may want to plot maps of the whole world, that little blue spinning sphere the surface of which provides a home for us all. Creating maps of smaller areas is covered in a tutorial I helped create called ‘Introduction to visualising spatial data in R’, hosted with data and code on a github repository. There are a range of options for plotting the world, including packages called maps, a function called
map_data from ggplot2 package and rworldmap.
In this post we will use the latter two (newer) options to show how maps of the entire world can easily be produced in R and overlaid with shortest-line paths called great circles. Amazingly, in each package, the geographic data for the world and many of its subregions are included, saving the need to download and store files of unknown quality from the internet.
Plotting continents and great circle lines in base graphics
The first stage is to load the packages we’ll be using:
Let us proceed by loading an entire map of the world from the rworldmap function
The above shows that in single line of code we have loaded
s, which represents the entire world and all its countries. This impressive in itself, and we can easily add further details like colour based on the countries’ attributes (incidentally, you can see the attribute data by typing
Adding points randomly scattered over the face of the Earth
But what if we want to add up points to the map of the world and join them up? This can be done in the same way as we’d add points to any R graphic. Using our knowledge of
bbox we can define the limits of random numbers (from
runif) to scatter points randomly over the surface of the earth in terms of longitude. Note the use of
cos(abs(l)) to avoid oversampling at the poles, which have a much lower surface area than the equator, per line of longitude.
Joining the dots
So how to join these randomly scattered points on the planet? A first approximation would be to join them with straight lines. Let’s join point 1, for example, to all others to test this method:
(Incidentally, isn’t the use of
segments here rather clunky - any suggestions of a more elegant way to do this welcome.) The lines certainly do join up, but something doesn’t seem right in the map, right? Well the fact that you have perfectly straight lines in the image means bendy lines over the Earth’s surface: these are not the shortest, great circle lines. To add these great circle lines, we must use the geosphere package:
Fantastic. Now we have great circle lines represented on a map with a geographic coordinate system (CRS) (as opposed to a projected CRS, which approximates Euclidean distance).
Beautifying the map
The maps we created so far are not exactly beautiful. Let’s try to make the map look a little nicer:
Doing it in ggplot2
The ‘beautified’ map above certainly is more interesting visually, with added colours. But it’s difficult to call it truly beautiful. For that, as with so many things in R plotting, we turn to ggplot2.
When we add the lines in projected maps (i.e. with a Euclidean coordinate system) based solely on origins and destinations, this works fine, but as with the previous example, generates incorrect shortest path lines:
Adding great circle lines to ggplot2 maps
Adding great circle lines in ggplot2 is similar, but we must save all of the coordinates of the paths in advance before plotting, because ggplot2 like to add all its layers in one function: you cannot iteratively add to the map using a
for loop as we did in the base graphics example above.
To create the for loop, first create a data frame of a single line. The iterate for all zones and use
rbind to place one data frame on top of the next:
To plot multiple paths, we can use the
geom_segment command. Before plotting the lines on the map, it’s sometimes best to first plot them on their own to ensure that everything is working. Note the use of the command
ggplot(), which initiates an empty ggplot2 instances, ready to be filled with layers. This is more flexible than stating the data at the outset.
Changing projection in ggplot
ggplot2 has inbuilt map projection functionality with the function
coord_map. This distorts the Euclidean axis of the map and allows some truly extraodinary shapes (these transformations can also be done in base graphics, e.g. by using
spTransform). However, as shown in the examples below, the library is currently buggy for plotting polygons.
We’ve seen 2 ways of plotting maps of the world and overlaying ‘great circles’ lines on them. There are probably more, but these two options seem to work well, except with the bugs in ggplot2 for plotting polygons in many map projections. The two methods are not incompatible (see
fortify for plotting sp objects in ggplot2) and can be combined in many other ways.
For more information on plotting spatial data in R, I recommend checking out R’s range of spatial packages. For an introductory tutorial on visualising spatial data in R, you could do much worse than start with Visualising Spatial Data in R by James Cheshire and myself.