I would like to produce a levelplot with divergent colors such that increasingly negative values of Z get darker in the first color and increasingly positive values get darker in the second color. this is common in cartography. I have tried tinkering with the col.regions argument but the best I can do is to get the split in the middle of my range of Z, but in my particular case range(Z) is (-1,12). I am using R 3.0.2 on OSX 10.9 Here is an example x <- y <- c(1:25) grid <- expand.grid(x=x,y=y) grid$z <- sort(runif(625,min=-1,max=12)) levelplot(z ~ x*y,grid) # produces the default pink and blue but the split is at ~5.5 # do something clever here # e.g., my.colors <- <create a palette that splits at zero> levelplot(z ~ x*y,grid,col.regions=my.colors) # so there should be some light pink at the bottom and the rest increasingly intense blue Ideas appreciated. Thanks in advance. Don McKenzie Research Ecologist Pacific Wildland Fire Sciences Lab US Forest Service Affiliate Professor School of Environmental and Forest Sciences University of Washington dmck at uw.edu
Use the Rcolorbrewer package. -- Bert On Fri, Nov 22, 2013 at 8:43 PM, Don McKenzie <dmck at u.washington.edu> wrote:> I would like to produce a levelplot with divergent colors such that increasingly negative values of Z get darker in the first color and increasingly > positive values get darker in the second color. this is common in cartography. I have tried tinkering with the col.regions argument but the best I can do > is to get the split in the middle of my range of Z, but in my particular case range(Z) is (-1,12). > > I am using R 3.0.2 on OSX 10.9 > > Here is an example > > x <- y <- c(1:25) > grid <- expand.grid(x=x,y=y) > grid$z <- sort(runif(625,min=-1,max=12)) > levelplot(z ~ x*y,grid) # produces the default pink and blue but the split is at ~5.5 > > # do something clever here > # e.g., my.colors <- <create a palette that splits at zero> > > levelplot(z ~ x*y,grid,col.regions=my.colors) # so there should be some light pink at the bottom and the rest increasingly intense blue > > Ideas appreciated. Thanks in advance. > > > > Don McKenzie > Research Ecologist > Pacific Wildland Fire Sciences Lab > US Forest Service > > Affiliate Professor > School of Environmental and Forest Sciences > University of Washington > > dmck at uw.edu > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.-- Bert Gunter Genentech Nonclinical Biostatistics (650) 467-7374
On Fri, 22 Nov 2013, Don McKenzie wrote:> I would like to produce a levelplot with divergent colors such that increasingly negative values of Z get darker in the first color and increasingly > positive values get darker in the second color. this is common in cartography. I have tried tinkering with the col.regions argument but the best I can do > is to get the split in the middle of my range of Z, but in my particular case range(Z) is (-1,12). > > I am using R 3.0.2 on OSX 10.9 > > Here is an example > > x <- y <- c(1:25) > grid <- expand.grid(x=x,y=y) > grid$z <- sort(runif(625,min=-1,max=12)) > levelplot(z ~ x*y,grid) # produces the default pink and blue but the split is at ~5.5 > > # do something clever here > # e.g., my.colors <- <create a palette that splits at zero> > > levelplot(z ~ x*y,grid,col.regions=my.colors) # so there should be some light pink at the bottom and the rest increasingly intense blue > > Ideas appreciated. Thanks in advance.One approach is to limit the range of colors (to match the range of the data) as you suggest above. The other approach is to extend the range of the legend (beyond the range of the data). For example: levelplot(z ~ x*y, grid, at = seq(-12, 12, length = 100)) This produces a legend that is symmetric around zero. For other/better diverging color palettes, you can use the RColorBrewer package (as suggested by Bert) or the colorspace package (see e.g., its graphical choose_color() tool).> > > Don McKenzie > Research Ecologist > Pacific Wildland Fire Sciences Lab > US Forest Service > > Affiliate Professor > School of Environmental and Forest Sciences > University of Washington > > dmck at uw.edu > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >
Barry Rowlingson
2013-Nov-26 08:25 UTC
[R] specify breaks in divergent palette in RColorBrewer: was divergent colors around zero in levelplot()
On Tue, Nov 26, 2013 at 1:02 AM, C. Alina Cansler <acansler at uw.edu> wrote:> Don, > > This looks helpful: > https://stat.ethz.ch/pipermail/r-help/2011-March/272361.htmlYes, he's a helpful chap. The fundamental problem here is the colour palette. When I was a boy all we had was a pen plotter with four coloured pens, and of course you could stick different coloured pens in the different pen slots and draw four different coloured lines. So your graphics package just said which number pen it was going to use and the colour that came out was up to you. Most R graphics functions still have this concept, although there may be over 100 pens and you don't end up swearing when one runs out of ink. A numeric value is converted to an integer and the integer does a lookup in a palette to get the colour. What you really want, and what my colourscheme package did, was to create functions that let users map values directly to colours. You could then plot points and lines using that function which meant totally controlled value-to-colour mappings that could be used across different plots if desired. That worked because points and lines lets you specify a colour value directly using something like col="#FF23EC" (as well as allowing col=23 and doing a palette lookup). But the image function (and probably levelplot) doesn't allow that so there's various tricks to make functional colour lookups work. I would convert the image matrix values to a matrix of colours, then create a matrix of the values 1:(n*m), and then image() that 1:(n*m) matrix using the colour matrix as a palette. That way each cell had its own palette entry, and you controlled that colour using the value-colour function. Or you could just use ggplot which I'm pretty sure has the same concept of mapping values to colours. Barry
Barry Rowlingson
2013-Nov-26 10:12 UTC
[R] specify breaks in divergent palette in RColorBrewer: was divergent colors around zero in levelplot()
On Tue, Nov 26, 2013 at 9:58 AM, Prof Brian Ripley <ripley at stats.ox.ac.uk> wrote:>> But the image function (and probably levelplot) doesn't allow that so > > Mis-information alert! The help says > > col: a list of colors such as that generated by ?rainbow?, > ?heat.colors?, ?topo.colors?, ?terrain.colors? or similar > functions. > > and look at what they generate. Or see e.g. ?col2rgb . > > Although base graphics has the concept of a palette of colours, AFAIK it > has always been bolted on top of a general colour specification, > originally RGB and for many years already RGBA.Yes image allows you to specify col=, but it always specifies a palette. The matrix values are scaled from 1:length(col) and looked up in that palette. You can't call image with z as matrix of colours and get those colours, nor set col to a matrix of colours and a see those colours laid out. This is unlike points() where specifying col= as a vector of the same length as the number of points gives you a 1:1 mapping of points to colours. To do image() with a 1:1 mapping of cell values to colours requires a tiny bit of hoop-jumping. Barry