3

I created a mixed density plot using ggplot2, I want to add summary information into the plot, namely the means of each density and 1 value that represents some sort of true mean.

Here is a simulated example borrowed from @Hernando Casas.

set.seed(1234)
data <- data.frame(value = rnorm(n = 10000, mean =50, sd = 20),
               type = sample(letters[1:2], size = 10000, replace = TRUE))
data$value[data$type == "b"] <- data$value[data$type == "b"] +
rnorm(sum(data$type == "b"), mean = 55)
library(ggplot2)
gp <- ggplot(data=data, aes_string(x="value"))
gp <- gp + geom_density(aes_string(fill="type"), alpha=0.3)

enter image description here

After added the summary information as vertical line. the plot looks like this

vlines <- data.frame(value = c(mean(data$value[data$type == "a"]), mean(data$value[data$type == "b"])),Mean = c("A", "B"))

gp2 <- gp + geom_vline(data=vlines,
                  aes(xintercept=value, colour=Mean),
                  size=1.05, linetype="dashed", show_guide=TRUE)
gp3 <- gp2+geom_vline(xintercept=(50+55+50)/2,
                size=1.05)

enter image description here

While the plot is exactly what I want, I'd like to add this solid black line into the legend under the box "Mean" with a name say "Overall". This is where I got stuck, I simply have no idea how to customize the legend since I don't have much experiences with ggplot2.

I found some example and modified my code

gp <- ggplot(data=data, aes_string(x="value"))
gp <- gp + geom_density(aes_string(fill="type"), alpha=0.3)

vlines <- data.frame(value = c(mean(data$value[data$type == "a"]), 
                           mean(data$value[data$type == "b"]),
                           (50+55+50)/2),
                 Mean = c("A", "B", "Overall"))

gp2 <- gp + geom_vline(data=vlines,
                  aes(xintercept=value, colour=Mean),
                  size=1.05, linetype="dashed", show_guide=TRUE)

enter image description here

Now I do have a legend, but I want to change the color of lines to be same as the density, more importantly I need to change the "Overall" line to solid dark color, again I ran into problem of customization.

I would really appreciate anyone's help. Thanks

Christopher B. L
  • 245
  • 4
  • 14

2 Answers2

4

Probably the easiest approach is just specifying a manual color-scale and linetype-scale as follows:

ggplot(data=data, aes(x=value)) + 
  geom_density(aes(fill=type), alpha=0.3) +
  geom_vline(data=vlines,
             aes(xintercept=value, colour=Mean, linetype=Mean),
             size=1.05, show_guide=TRUE) +
  scale_color_manual(values = c("red","green","black")) +
  scale_linetype_manual(values = c(2,2,1)) +
  theme_bw()

which gives:

enter image description here

Heroka
  • 12,889
  • 1
  • 28
  • 38
Jaap
  • 81,064
  • 34
  • 182
  • 193
  • To get the exact same colours as the fill, you could use `scale_color_manual(values = c("#F8766D","#00BFC4","black"))`. Source: gg_color_hue function from http://stackoverflow.com/a/8197703/5020008 – Heroka Nov 04 '15 at 10:13
  • `show_guide` is deprecated. It is now called as `show.legend` – patL Jun 21 '18 at 10:38
2

Using the following "hack" (using your gp2), creating a manual color scale using scale_color_manual, you get a solid line for the overall mean and a legend entry for "overall" - but in the legend, the linetype of "overall" is still dashed:

gp3 <- gp2+geom_vline(mapping=aes(color="Overall", xintercept=(50+55+50)/2), 
                      linetype="solid", size=1.05)
cols <- c('black', 'red', 'green')
names(cols) <- c("Overall", "A", "B")
gp4 <- gp3 + scale_color_manual(values = cols, name = "Mean") 

As far as I understand the legend functionality of ggplot2, I think it is not possible to do that what you actually want: Any legend box (like "mean" and "type" in your example) distinguishes exactly one graphical characteristic, like color, linetype, etc... What you want, is a mixture of characteristics (different combinations of color and linetype) in one legend box. Perhaps you consider to introduce a new legend box for the overall mean?

EDIT: It's possible to specify a manual color scale and linetype scale in one box, see Jaap's post :)

Patrick Roocks
  • 3,129
  • 3
  • 14
  • 28
  • Thanks very much, it is very helpful. I see your points, in my case I probably should create a new legend box, could I bother you one more time about how to do that? – Christopher B. L Nov 04 '15 at 08:29