How to improve a spatial raster map using ggplot when compared to spplot?
Asked Answered
P

3

8

How can I improve the legend of spatial raster map plot using ggplot when compared to a spplot() legend?

I would like plot spatial maps using ggplot() instead of ssplot() however there are a few things that I would like to improve when compared to the spplot:

  1. create a ggplot legend that goes from small (bottom) to large values (top)
  2. Have the breaks in the ggplot legend similar to the ssplot() legend so that I know what the boundaries are of each color.

## load packages
require(raster)
require(ggplot2)
require(rgdal)
require(RColorBrewer)
set.seed(1)

r <- raster(xmn=-110, xmx=-90, ymn=40, ymx=60, ncols=40, nrows=40,
          crs="+proj=lcc +lat_1=48 +lat_2=33 +lon_0=-100
+ellps=WGS84")
r <- setValues(r,matrix(rnorm(1600, mean=0.4,sd=0.2))) 

## 1. spatial map with spplot
cuts <-seq(minValue(r),maxValue(r),length.out=8)
cuts = round(cuts,digits=2)
col.regions = brewer.pal(length(cuts)+3-1, "RdYlGn")
print( 
spplot(as(r, 'SpatialGridDataFrame'),at=cuts,
col.regions=col.regions,
colorkey=list(labels=list(at=cuts),at=cuts), pretty=TRUE,
scales=list(draw=T)
) 
)

## 2. spatial map with ggplot
p = rasterToPoints(r); df = data.frame(p)
colnames(df) = c("x", "y", "NDVI")

p  <- ggplot(data=df) + geom_tile(aes(x, y, fill=NDVI)) +
coord_equal() + labs(x=NULL, y=NULL) + 
scale_fill_gradient2(low="red", mid="yellow",high="green",
limits=c(minValue(r),maxValue(r)), midpoint = 0.4) + theme_bw() +
scale_x_continuous(expand=c(0,0)) + scale_y_continuous(expand=c(0,0))
print(p)

ssplot() result ssplot

ggplot() result ggplot

Polyzoic answered 28/7, 2011 at 16:46 Comment(2)
Please don't use red-green colour contrasts. The 5-10% of men with red-green colour weakness will find them very hard to read.Circumfluous
the link to Koske's site - illustrates more or less what I would like to do. I'll explore ggplot() capacity further, adjust colors,improve legend and post an update below. All tips/examples are welcome. ThanksPolyzoic
L
5

thanks @joran for the pointer to that.

here is an example code and output using the dev version:

br <- seq(min(df$NDVI), max(df$NDVI), len=8)

ggplot(data=df) + 
  geom_tile(aes(x, y, fill=NDVI)) + 
  scale_fill_gradient(low="red", high="green", 
    breaks=br, labels=sprintf("%.02f", br), 
    guide=guide_colorbar(title=NULL, nbin=100, barheight=unit(0.75, "npc"), label.hjust=1)) + 
  scale_x_continuous(expand=c(0,0)) + 
  scale_y_continuous(expand=c(0,0))

enter image description here

you can probably try this by:

# from Hadley's instruction
install.packages("devtools")
library(devtools)
dev_mode() # to avoid interfering with your existing install
install_github("ggplot2", username="kohske", branch = "feature/new-guides-with-gtable")
library(ggplot2)

UPDATED:

here is the instruction for the installation from scratch:

install.packages(
  c('devtools', 'digest', 'memoise', 'plyr', 'reshape2', 'RColorBrewer', 'stringr', 'dichromat', 'munsell', 'plyr', 'colorspace'), 
  dep=TRUE)

library(devtools)
dev_mode()

install_github("scales")
install_github("ggplot2", username="kohske", branch = "feature/new-guides-with-gtable")
Lamere answered 29/7, 2011 at 16:56 Comment(4)
I just tried it but I get the following error: when building ‘ggplot2_0.9.0.tar.gz’ ERROR: dependency ‘scales’ is not available for package ‘ggplot2’, it says that scales is not available for 2.13.0 where can I find it? It would be great to make legends such as the one above. Great.Polyzoic
I found scales on github github.com/hadley/scales, what is the best way to install this in R?Polyzoic
The answer was updated. try install_github("scales"). if you get errors such as missing packages RColorBrewer, stringr, dichromat, munsell, plyr, colorspace, then try install.packages(c('RColorBrewer', 'stringr', 'dichromat', 'munsell', 'plyr', 'colorspace'), dep=TRUE)Lamere
thanks great! this works well. I will now try to improve the colors so that different levels have clear colors (regarding the remark of Hadley.Polyzoic
S
4

I'm not sure how to address (1) off the top of my head. But here are some possible solutions for (2) and (3).

I don't believe that ggplot2 currently is capable of labeling the legend in that manner. However, Koske has been working on some code that may be rolled into ggplot2 in the future that creates legends that are styled in this manner. Here is a link, although it will require installing some additional packages and is only alpha.

To get the specific breaks you're looking for, try this:

br <- c(-0.25,-0.05,0.15,0.35,0.56,0.76,0.96,1.16)
p  <- ggplot(data=df) + geom_tile(aes(x, y, fill=NDVI)) +
coord_equal() + labs(x=NULL, y=NULL) + 
scale_fill_gradient(low="red", mid="yellow",high="green",
breaks = br) + theme_bw() +
scale_x_continuous(expand=c(0,0)) + scale_y_continuous(expand=c(0,0))
print(p)

which produced this graph on my machine:

enter image description here

I have not tested what this would look like using the experimental code mentioned above.

Strafford answered 28/7, 2011 at 20:6 Comment(3)
The only way I can think of to get a high-to-low legend without hacking the internals of the ggplot code is to make the scale into a factor with cut, assign the colours by hand, and reverse the order of the levels ...Bluh
thanks for the link too the site of Koske, that is precisely what I would like to do with the legend of a ggplot spatial map. I'll do some testing a will post a final result below soon.Polyzoic
note that the codes are outdated. Please find this post to ggplot2 list: groups.google.com/group/ggplot2/browse_thread/thread/…Lamere
P
0

Re: (2) First cut() your data to get a binned dataset. Use breaks and labels options in cut() to obtain the correct labels, e.g.:

dat$col <- cut(
  df$NDVI, 
  breaks=c(-Inf, -0.25, 0.05, ...whatever..., Inf), 
  labels=c(-0.25, 0.05, ...whatever..., "")
)

Then you can plot using ggplot and shifting the labels so that they are right on the color boudaries using:

 scale_fill_manual (your options...) + guides(fill=guide_legend(label.vjust = 1.2)) #1.2= what fits your legend best. Use label.hjust if using an horizontal color bar

See also: Generating a color legend with shifted labels using ggplot2

Alternatively, you can create the color legend with an external script (e.g. GrADS makes nice color legends using the right scripts) and specify the same colors manually in scale_fill_manual.

Pinkeye answered 20/11, 2014 at 11:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.