EcoPress

This is how I did it… Mapping in R with ‘ggplot2’

by Andrew Tredennick

Recently I moved from ArcMap to R do a lot of my spatial analysis and map making. In particular, I’ve started to use the ‘ggplot2’ to create what I think are exceptionally good-looking maps (no offense to ArcMap, but something about ‘ggplot2’ maps are just so crisp). A couple of people have asked for some code to help them on their way with map making in R, so here is a simple snippet of code I used to make a rainfall map of sub-Saharan Africa with a fake transect.

A couple notes.

  1. You will need the ‘raster’ and ‘ggplot2’ packages installed. In R this is easily achieved from command line via, install.packages(“ggplot2”) and install.packages(“raster”). Some R interfaces (like RStudio) also have easy-to-use GUIs to help install new packages
  2. In this code I am creating the map from an ASCII file as exported from ArcMap (it was a raster I exported as ASCII).

The code.

rm(list=ls()) #clear workspace

#load libraries
library(raster)
library(ggplot2)

#open ASCII file using ‘raster’ command, which converts the ASCII to a raster object
map <- raster(“/your/path/to/file.asc”)

#convert the raster to points for plotting
map.p <- rasterToPoints(map)

#Make the points a dataframe for ggplot
df <- data.frame(map.p)
#Make appropriate column headings
colnames(df) <- c(“Longitude”, “Latitude”, “MAP”)

#Call in point data, in this case a fake transect (csv file with lat and lon coordinates)
sites <- data.frame(read.csv(“/your/path/to/pointfile.csv”))

#Now make the map
ggplot(data=df, aes(y=Latitude, x=Longitude)) +
geom_raster(aes(fill=MAP)) +
geom_point(data=sites, aes(x=x, y=y), color=”white”, size=3, shape=4) +
theme_bw() +
coord_equal() +
scale_fill_gradient(“MAP (mm/yr)”, limits=c(0,2500)) +
theme(axis.title.x = element_text(size=16),
axis.title.y = element_text(size=16, angle=90),
axis.text.x = element_text(size=14),
axis.text.y = element_text(size=14),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
legend.position = “right”,
legend.key = element_blank()
)

The product.

I’ve only allowed the colors to go up to 2,500 mm annual rainfall because I wanted to show how most of Africa has rainfall levels below 2,500 mm/yr. You can change this by messing with colors and the ‘scale_fill_gradient()’ command. ggplot2 has great online resources here, http://docs.ggplot2.org/current/#.

Rplot01

If you have any questions (e.g., about the specific commands within the ggplot call), post them in the comments and I’ll address them.

From the comments: here’s a comparison using the base R plotting commands. I didn’t work to match the colors because I was using default ggplot2 colors and wanted to compare with default base colors (one of the many great things about ggplot2 is pleasing default color options). Also notice the difference in tick positions and spacing. Of course, I could make this look a lot better, but that would take more work than it takes using ggplot2. Just my opinion though!

Rplot03

Do you have any great science tricks you want to share? Email us at nrel.ecopress@gmail.com or tell us on Facebook, http://www.facebook.com/nrelscience.

24 comments

  1. Seema Sheth

    Thanks, Andrew–looks great. I think Latitude and Longitude axes should be switched. I am curious if you could explain the advantage of converting raster to points and using ggplot2 instead of just plot(map) and then points(sites$x,sites$y). Thanks again!

    • Andrew Tredennick

      Whoops! Thanks Seema, good catch!

      The advantage of ggplot2, in my mind, over the base plotting commands in R is (1) aesthetics, and (2) options. I think ggplot just makes beautiful plots compared the base “plot()”. And, once you get to know your way around ggplot2, it is easier to customize the plot to make it do almost anything you want. This is a pretty simple example, but what ggplot really excels at is making complicated figures easy to make — and making it easy to produce high-quality, publication-ready figures.

      I’ll add a map using the base plotting commands for comparison.

  2. Seema Sheth

    Wow, it’s really helpful to see the two plots side by side. Your point is taken–it seems like you can produce a nice map more quickly and effortlessly using ggplot2. Thanks for the explanation–I’ll have to try this method out next time!

  3. Kristin

    Hi Andrew,

    Thanks for the great code. I have a problem I keep getting an error “cannot find function geom_raster” after this snippet of code
    ‘ ggplot(data=df, aes(y=Latitude, x=Longitude)) +
    geom_raster(aes(fill=MAP)) +’

    I installed ggplot2, raster, and called them. Do you know why this is occuring? Thank you. Kristin

    • Andrew Tredennick

      I’ve done some quick googling and nothing jumped out. What version of R are you using? Do other ggplot2 functions work (like if you were just making an x-y scatterplot with geom_point?

      • Kristin

        Andrew,
        I am sorry, it was my mistake i forgot the (+) after the statement. I am having some other issues if you are up to helping.
        In your example, under column headings, what does MAP represent? Are those points? Do I need such a column? Is MAP a column in your .csv file with the lat/long points?

        I already have my ascii converted to raster(used arcmap, although I did load the ascii to follow your example), how do I just load the raster into ggplot and plot it?

        thanks for your time.

  4. Andrew Tredennick

    Hi Kristin,
    Happy to help! I am traveling today though, so will have to get back to you. In short though, MAP is mean annual precipitation at a particular lat and long. So, yes, in a way you will need some “data” associated with each lat/long point (which in this case they are, and ggplot turns it into a grid). I tend to read in ascii rather than raster because it is faster and easier to manipulate if I have to. Hope that helps a little!

  5. Pingback: This is how I did it…learned R. | EcoPress

  6. Pingback: How to create maps in R | funature blog

  7. John Gross

    Andrew,
    Very interesting! I noted your map of Africa looks geographically “correct”, but when converting the raster to a data frame the CRS info is lost. I frequently use projectRaster or spTransform to deal with CRS mismatches and to make plots look like we expect, and I’m wondering if (1) there are issues with this when using ggplot and converting rasters to data frames, and (2) if you have suggestions for handling projections so maps look like we expect – i.e. projected to Albers or similar. I have used ggplot with spatial objects and this seems like an interesting application.

    • Andrew Tredennick

      John- Yes, the CRS info is lost, but I retain the lat/longs as columns in the data frame. Then using the ‘coord_equal()’ function in ggplot2 tends to make things look right. So far I have only done this using GCS and sinusoidal projections, so I honestly don’t know how different projections would look, but I imagine retaining x,y info in the data frame does the trick. I haven’t had a problem yet converting rasters to data frames, except that for high resolution data this can be a bit slow. R isn’t that great at large matrix processing — if really doing “big” spatial work, IDL and Matlab are more efficient. What kind of issues are you concerned about when converting raster to data frame?

  8. Jien Zhang

    Hi Andrew,

    I am totally fresh with R but your code does help me a lot! I have a bunch of files needs to be plotted. However, the longitude and latitude of these files are not equal. When I tried a couple of them using your approach, I found that the width and height of the two maps are different. I am wondering if you have solutions to make maps with fixed size. In another word, could you set boundaries for the map manually? I really appreciate you can help me with this. Thanks.

    • Andrew Tredennick

      Hi Jien,

      I’m traveling right now, so unable to give this my full attention. I’ll post a response early next week. Thanks for your patience!

  9. Pingback: Smoothing out ggplot2 map | Solutions for enthusiast and professional programmers

  10. Pingback: Smoothing out ggplot2 map | FYTRO SPORTS

  11. Pingback: This is how I did it … added error bars to a lattice bar chart in R | EcoPress

  12. L. Hill

    Lovely post and lovely maps – thank you! I was just wondering if you had any advice on the best way to export maps from R to keep them nice and crisp? Always a tricky one and particularly important for maps!

    • Andrew Tredennick

      I like .png files for maps (really, for all my figures). Take a look at the ggsave() function, and the dpi= setting inside of it to set the resolution. Good luck!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: