[R-sig-Geo] Adding a scale bar and north arrow to a ggplot

Paul Hiemstra p.hiemstra at geo.uu.nl
Thu Nov 18 21:12:57 CET 2010


Dear list,

A common addition to any spatial plot are a north arrow and a scale bar. 
I've searched online for a straightforward way to add those to a ggplot 
plot. I then decided to give a go myself. A crude first attempt for an 
automatic scalebar addition function is listed below. The example works 
for the meuse dataset, but a second with a different dataset did yield 
good results.

My question to you is: is there anyone who has some good tips / example 
code to add a north arrow and a scalebar to a ggplot image. Any 
expansions on the code below are also welcome.

cheers,
Paul

ps Some info on my system is listed at the very bottom

library(sp)
library(ggplot2)

data(meuse)
data(meuse.grid)

string.length = function(s) {
#  browser()
   if(!is.character(s)) s = as.character(s)
   length(strsplit(s, "")[[1]])
}

makeNiceNumber = function(num, num.pretty = 1) {
   noNumbers = string.length(as.character(round(num)))
   return(round(num / 10^(noNumbers - num.pretty)) * 10^(noNumbers - 
num.pretty))
}

makeScaleBar = function(obj, plotname, xname = "x", yname = "y", unit = 
"m", placement = "bottomright") {
#     browser()
   range_x = max(obj[[xname]]) - min(obj[[xname]])
   range_y = max(obj[[yname]]) - min(obj[[yname]])
   if(placement == "bottomright") {
     xcoor.max = makeNiceNumber(max(obj[[xname]]) - (0.05 *range_x ), 
string.length(round(max(obj[[xname]]))) - string.length(round(0.3 * 
range_x)))
     xcoor.min = makeNiceNumber(max(obj[[xname]]) - (0.5 *range_x ), 
string.length(round(max(obj[[xname]]))) - string.length(round(0.3 * 
range_x)))
     ycoor = min(obj[[yname]]) + (0.05 * range_y)
   } else {
     xcoor.min = makeNiceNumber(max(obj[[xname]]) - (0.95 *range_x ), 
string.length(round(max(obj[[xname]]))) - string.length(round(0.3 * 
range_x)))
     xcoor.max = makeNiceNumber(max(obj[[xname]]) - (0.5 *range_x ), 
string.length(round(max(obj[[xname]]))) - string.length(round(0.3 * 
range_x)))
     ycoor = min(obj[[yname]]) + (0.95 * range_y)
   }
   scalebar.data = data.frame(x = c(xcoor.max, xcoor.min), y = ycoor, 
lbl = c(paste(xcoor.max - xcoor.min, unit), 0))
   scalebar.data[[plotname]] = min(obj[[plotname]])
   return(list(geom_path(aes(x = x, y = y), data = scalebar.data, lwd = 
2, color = "black"),
           geom_text(aes(x = x, y = y, label = lbl), data = 
scalebar.data, vjust = 1.3)))
}

sb = makeScaleBar(meuse.grid, "dist", placement = "topright")
ggplot(aes(x  = x, y = y, fill = dist), data = meuse.grid) + geom_tile() 
+ sb[[1]] + sb[[2]]

R version 2.12.0 (2010-10-15)
Platform: i486-pc-linux-gnu (32-bit)

locale:
  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C
  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8
  [5] LC_MONETARY=C              LC_MESSAGES=en_US.UTF-8
  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C
  [9] LC_ADDRESS=C               LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C

attached base packages:
[1] grid      stats     graphics  grDevices utils     datasets  methods
[8] base

other attached packages:
[1] ggplot2_0.8.7 digest_0.4.2  reshape_0.8.3 plyr_0.1.9    proto_0.3-8
[6] sp_0.9-62

loaded via a namespace (and not attached):
[1] lattice_0.19-13

hiemstra at fg-113:~$ uname -a
Linux fg-113 2.6.32-21-generic #32-Ubuntu SMP Fri Apr 16 08:10:02 UTC 
2010 i686 GNU/Linux

-- 
Drs. Paul Hiemstra
Department of Physical Geography
Faculty of Geosciences
University of Utrecht
Heidelberglaan 2
P.O. Box 80.115
3508 TC Utrecht
Phone:  +3130 253 5773
http://intamap.geo.uu.nl/~paul
http://nl.linkedin.com/pub/paul-hiemstra/20/30b/770



More information about the R-sig-Geo mailing list