3

I want to create a ggplot in which a statistical parameter varies according to an aesthetically mapped factor. Specifically, I'd like to create a contour plot using stat_density2d(), I'd like to to map a discrete factor to the color, and I'd like to specify different break values for each factor level.

Here's a minimal working example:

d <- data.frame(x=c(rnorm(500), rnorm(500, 2)), y=rnorm(1000), z=c(rep("a", 500), rep("b", 500)))

ggplot(d, aes(x, y, fill=z)) + 
      stat_density2d(breaks=.05, geom="polygon", alpha=.5)

enter image description here

This is what I'm going for except the breaks are identical across factors. I'm looking for a way to specify different break values for each factor. One way to do that would be to create a separate layer for each factor:

ggplot() + 
      stat_density2d(data=d[d$z=="a",], aes(x, y), breaks=.05, geom="polygon", alpha=.5, fill="red") +
      stat_density2d(data=d[d$z=="b",], aes(x, y), breaks=.1, geom="polygon", alpha=.5, fill="blue")

enter image description here

But this isn't workable because I lose the legend and it's too cumbersome for cases with more than two factor levels.

I'd like to combine the strengths of the above two cases. I'm almost positive I've seen a way to accomplish what I'm trying to do, but can't seem to find it now that it's relevant. Anybody have thoughts on a possible solution?

mmk
  • 514
  • 1
  • 3
  • 12
  • 1
    I've never seen anything like a way to do that inside ggplot, but I think you could do this fairly easily either by (a) pre-processing your data, or (b) transforming your data. – Gregor Thomas Dec 06 '14 at 01:35

1 Answers1

5

Remebered this from a couple of years ago - so taking the solution directly from Kohske's answer

# Data
set.seed(1)    
d <- data.frame(x=c(rnorm(500), rnorm(500, 2)), y=rnorm(1000), 
                                   z=c(rep("a", 500), rep("b", 500)))

library(plyr)
library(ggplot2)

hls <- mapply(function(x, b) stat_density2d(data = x, breaks = b, 
                    geom="polygon", alpha=.5), dlply(d, .(z)), c(0.05, 0.1))

ggplot(d, aes(x, y, fill=z)) + hls + scale_fill_manual(values=c("red", "blue"))

enter image description here

# Compare
ggplot() + 
  stat_density2d(data=d[d$z=="a",], aes(x, y), breaks=.05, geom="polygon", 
                                                      alpha=.5, fill="red") +
  stat_density2d(data=d[d$z=="b",], aes(x, y), breaks=.1, geom="polygon",
                                                     alpha=.5, fill="blue")
Community
  • 1
  • 1
user20650
  • 24,654
  • 5
  • 56
  • 91
  • 1
    This is another thing to learn today. I will check Kohske's post as well. Thanks for sharing this idea. – jazzurro Dec 06 '14 at 02:29