Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Plot multivariate Gaussian contours with ggplot2

Tags:

r

ggplot2

I'm trying to augment a plot with contours from a 2D Gaussian distribution with known mean and covariance. Ideally I would just have to specify the function and it would be plotted in 2D (like stat_function except for 2 dimensions). I can do it with geom_raster by generating a grid of probabilites. Can I use geom_contour2d somehow instead?

m <- c(.5, -.5)
sigma <- matrix(c(1,.5,.5,1), nrow=2)
data.grid <- expand.grid(s.1 = seq(-3, 3, length.out=200), s.2 = seq(-3, 3, length.out=200))
q.samp <- cbind(data.grid, prob = mvtnorm::dmvnorm(data.grid, mean = m, sigma = sigma))
ggplot(q.samp, aes(x=s.1, y=s.2)) + 
    geom_raster(aes(fill = prob)) +
    coord_fixed(xlim = c(-3, 3), ylim = c(-3, 3), ratio = 1)

enter image description here

like image 303
James Owers Avatar asked Mar 25 '16 14:03

James Owers


People also ask

How to create a 2D density contour plot in ggplot2?

The geom_density_2d_filled function The geom_density_2d function A 2D density contour plot can be created in ggplot2 with geom_density_2d. You just need to pass your data frame and indicate the x and y variable inside aes.

What are contour plots used for?

In general, contour plots are useful for functions of two variables (like a bivariate gaussian density). We’ll look at examples in the next section.

What are the disadvantages of using Ggplot2?

The disadvantage with ggplot2 is that it is not possible to get multiple Y-axis on the same plot. To plot multiple time series on the same scale can make few of the series appear small. An alternative would be to facet_wrap it and set the scales='free'.

How to make a plot using ggplot?

First, you need to tell ggplot what dataset to use. This is done using the ggplot (df) function, where df is a dataframe that contains all features needed to make the plot. This is the most basic step.


2 Answers

I was barking up the wrong tree looking at 2d stuff. You can achieve what I want with geom_contour and by adding a z aesthetic:

m <- c(.5, -.5)
sigma <- matrix(c(1,.5,.5,1), nrow=2)
data.grid <- expand.grid(s.1 = seq(-3, 3, length.out=200), s.2 = seq(-3, 3, length.out=200))
q.samp <- cbind(data.grid, prob = mvtnorm::dmvnorm(data.grid, mean = m, sigma = sigma))
ggplot(q.samp, aes(x=s.1, y=s.2, z=prob)) + 
    geom_contour() +
    coord_fixed(xlim = c(-3, 3), ylim = c(-3, 3), ratio = 1) 

enter image description here

like image 79
James Owers Avatar answered Nov 07 '22 15:11

James Owers


I would use the ellipse package to construct the contour data directly. This still requires a separate call to construct the data, but is much more efficient (in both space and time) than your solution of constructing an entire grid and then finding the contours.

library(ellipse)
library(plyr)  ## not necessary, but convenient
m <- c(.5, -.5)
sigma <- matrix(c(1,.5,.5,1), nrow=2)
alpha_levels <- seq(0.5,0.95,by=0.05) ## or whatever you want
names(alpha_levels) <- alpha_levels ## to get id column in result
contour_data <- ldply(alpha_levels,ellipse,x=sigma,
      scale=c(1,1),  ## needed for positional matching
      centre=m)

(you could use lapply and rbind from base R; plyr::ldply is just a shortcut)

Now plot:

library(ggplot2)
ggplot(contour_data,aes(x,y,group=.id))+geom_path()
like image 28
Ben Bolker Avatar answered Nov 07 '22 16:11

Ben Bolker