Generating visually appealing density heat maps in R

While I know that there are a series of functions for generating heat maps in R, the problem is that I'm unable to produce visually appealing maps. For example, the images below are good examples of heat maps I want to avoid. The first clearly lacks detail, while the other one (based on the same points) is too detailed to be useful. Both plots have been generated by the density() function in the spatstat R package.

How can I get more "flow" into my plots? What I'm aiming for is more of the look the results of the commercial SpatialKey (screenshot) software is able to produce.

Any hints, algorithms, packages or lines of code that could take me in this direction?

-
have you looked at the image() function? Increasing the number of breaks increases resolution. – Macro Apr 18 '12 at 13:37

There are two things that will impact the smoothness of the plot, the bandwidth used for your kernel density estimate and the breaks you assign colors to in the plot.

In my experience, for exploratory analysis I just adjust the bandwidth until I get a useful plot. Demonstration below.

library(spatstat)
set.seed(3)
X <- rpoispp(10)
par(mfrow = c(2,2))
plot(density(X, 1))
plot(density(X, 0.1))
plot(density(X, 0.05))
plot(density(X, 0.01))


Simply changing the default color scheme won't help any, nor will changing the resolution of the pixels (if anything the default resolution is too precise, and you should reduce the resolution and make the pixels larger). Although you may want to change the default color scheme for aesthetic purposes, it is intended to be highly discriminating.

Things you can do to help the color are change the scale level to logarithms (will really only help if you have a very inhomogenous process), change the color palette to vary more at the lower end (bias in terms of the color ramp specification in R), or adjust the legend to have discrete bins instead of continuous.

Examples of bias in the legend adapted from here, and I have another post on the GIS site explaining coloring the discrete bins in a pretty simple example here. These won't help though if the pattern is over or under smoothed though to begin with.

Z <- density(X, 0.1)
logZ <- eval.im(log(Z))
bias_palette <- colorRampPalette(c("blue", "magenta", "red", "yellow", "white"), bias=2, space="Lab")
norm_palette <- colorRampPalette(c("white","red"))
par(mfrow = c(2,2))
plot(Z)
plot(logZ)
plot(Z, col=bias_palette(256))
plot(Z, col=norm_palette(5))


To make the colors transparent in the last image (where the first color bin is white) one can just generate the color ramp and then replace the RGB specification with transparent colors. Example below using the same data as above.

library(spatstat)
set.seed(3)
X <- rpoispp(10)
Z <- density(X, 0.1)
A <- rpoispp(100) #points other places than density

norm_palette <- colorRampPalette(c("white","red"))
pal_opaque <- norm_palette(5)
pal_trans <- norm_palette(5)
pal_trans[1] <- "#FFFFFF00" #was originally "#FFFFFF"

par(mfrow = c(1,3))
plot(A, Main = "Opaque Density")
plot(A, Main = "Transparent Density")

pal_trans2 <- paste(pal_opaque,"50",sep = "")
plot(A, Main = "All slightly transparent")


-
Thank you, very clearly resented answer. This combined with the "spatstat.options(npixel=c(100,100))" command you lined to did the trick. If I can bother you some more: Do you know how I can make the "background" color transparent? – Figaro Apr 19 '12 at 7:34
@Figaro, I have updated with an example of making the colors semi-transparent. – Andy W Apr 19 '12 at 12:20
Thank you. One more thing. While this might be slightly off topic: How do I export these heatmaps into a Shape file? Or am I required to treat them as rasters only? – Figaro Apr 19 '12 at 12:37
I've never had to do that, so I can't say offhand. Probably a good question for the R guru's on stackoverflow. – Andy W Apr 19 '12 at 12:49
Can a heatmap be presented as anything else than a raster? – Figaro Apr 19 '12 at 12:53

You may benefit from the interp function from the akima package. This will let you interpolate your matrix to another resolution if need be. To make something like your linked example, you would need to interpolate to a pretty fine grid (perhaps with the arguments xo and yo being ~ 1000 in length). This will give you a new matrix that you can plot with image(). If you want transparency, this will take some additional work. It's not easy to do that with a color palette, so you may end up having to plot each grid as a polygon with an assigned color.

-
Do you have experience with creating the transparency? Are there examples? That would be the next step. – Figaro Apr 19 '12 at 6:04
How do I create the x, y, z values needed for the interp()? For example, if density() uses a 100x100 grid, I have the z values for each point, but I do not have the x & y in the required vector format (I only have the coordinates of the axles). – Figaro Apr 19 '12 at 7:31
Made a loop to get the coordinate pairs, but is there a function for this? – Figaro Apr 19 '12 at 8:26
Looks like image can accept transparent colors after all. See: menugget.blogspot.de/2012/04/… . In case you still want to use interp, you can generate your xy coordinate combinations for your z levels with : "grid <- expand.grid(x=x,y=y)" – Marc in the box Apr 19 '12 at 10:59

You may want to look into ggplot2. It seems like the package you've tried doesn't have a great color schemes or "flow" -- take a look at RColorBrewer. There is a blog where it implemented these package with a simple example.

I'm not sure if you are trying to plot geographical data as shown in your linked example, but if you do I know that Google offers "Static Maps API V2 Developer Guide" and you can combine Google and R with a package called, RgoogleMaps.

Have you tried cranking up the resolution in density? Try argument dimyx=c(512, 512) or higher.