22

I can generate a density plot of 1D data with:

qplot(mydatapoints, geom='density')

I've also seen plenty of examples of heatmap grids, but these are more akin to histograms for 1D data in that data goes into discrete buckets instead of showing a smooth curve.

Can I plot something similar to the 1D density but for 2D data, with (say) something like hue/saturation/lightness to represent the density?

Yang
  • 16,037
  • 15
  • 100
  • 142

3 Answers3

29

I think you want a 2D density estimate, which is implemented by kde2d in the MASS package.

df <- data.frame(x=rnorm(10000),y=rnorm(10000))

via MASS and base R:

k <- with(df,MASS:::kde2d(x,y))
filled.contour(k)

via ggplot (geom_density2d() calls kde2d())

library(ggplot2)
ggplot(df,aes(x=x,y=y))+geom_density2d()

I find filled.contour more attractive, but it's a big pain to work with if you want to modify anything because it uses layout and takes over the page layout. Building on Brian Diggs's answer, which fills in colours between the contours: here's the equivalent with different alpha levels, with transparent points added for comparison.

ggplot(df,aes(x=x,y=y))+
  stat_density2d(aes(alpha=..level..), geom="polygon") +
  scale_alpha_continuous(limits=c(0,0.2),breaks=seq(0,0.2,by=0.025))+
  geom_point(colour="red",alpha=0.02)+
  theme_bw()

enter image description here

mchen
  • 9,808
  • 17
  • 72
  • 125
Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
  • 1
    Any ideas if the data is more sparse than this? I'm getting small patches in some places but no coverage in others. – CodeGuy May 12 '14 at 21:30
  • 1
    You might be able to increase the smoothing parameter of the kernel density estimator. – Ben Bolker May 12 '14 at 21:53
9

Combining two other answers (one pointing to geom_density2d and one giving sample data and scale_colour_gradient):

df <- data.frame(x=rnorm(10000),y=rnorm(10000))
ggplot(df,aes(x=x,y=y))+
    stat_density2d(aes(fill=..level..), geom="polygon") +
    scale_fill_gradient(low="blue", high="green")
Brian Diggs
  • 57,757
  • 13
  • 166
  • 188
1

There's also scale_colour_gradient()

df <- data.frame(x=rnorm(10000),y=rnorm(10000))
ggplot(df, aes(x,y,colour=y)) + geom_point() + scale_colour_gradient(low="blue",high="red")
Brandon Bertelsen
  • 43,807
  • 34
  • 160
  • 255