John Smith John Smith - 1 year ago 69
R Question

legend not plotting in multiple densities plot using ggplot2

As title says the function below that plots a number of densities from the data passed, does not plot the legend. MWE:

plotDensities <- function(xlab="", xlim=c(), ...) {
datas <- list(...)
cbPalette <- c("#000000", "#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7")
if (length(datas) > length(cbPalette)) return(invisible(NULL))
dplot <- ggplot() + xlab(xlab) +
scale_colour_manual(values=setNames(cbPalette[1:length(datas_names)], datas_names)) +
theme(legend.position = c(.8, .8))
datas_names <- names(datas)
for (i in 1:length(datas)) {
name <- datas_names[i]
values <- data.frame(x=datas[[name]])
dplot <- dplot + geom_density(aes(x=x), colour=cbPalette[i], data=values)
if (!is.null(xlim))
dplot <- dplot + xlim(xlim)

v1 <- rnorm(2000, 0, 1)
v2 <- rnorm(3000, 1, 1.5)
v3 <- rnorm(4000, 2, 2.5)
dplot <- plotDensities(xlim="whatever", v1=v1, v2=v2, v3=v3)

Answer Source

ggplot generates a legend when you map a column in your data to an aesthetic (e.g., colour, fill, etc.) inside aes. However, your code is setting colour outside of aes in your call to geom_density, which won't produce a legend.

In addition, your data is split up into separate vectors. However, ggplot works best when you have a single data frame in "long" format. In this case, that means combining v1, v2 and v3 into a single data frame with another column marking which vector each row originally came from.

Here's a simple example, using your data, that you can adapt into your function:

# Convert data to long format
dat = data.frame(vals=c(v1,v2,v3), 
                 source=rep(c("v1","v2","v3"),sapply(list(v1,v2,v3), length))) 

           vals source
1    -0.2860619     v1
2     1.8072476     v1
3    -0.6492385     v1
8998  3.8989335     v3
8999  5.1929588     v3
9000  1.8716558     v3
ggplot(dat, aes(vals, colour=source)) +
  geom_density() +

enter image description here