How to overlay density plots in R?

194,909

Solution 1

use lines for the second one:

plot(density(MyData$Column1))
lines(density(MyData$Column2))

make sure the limits of the first plot are suitable, though.

Solution 2

ggplot2 is another graphics package that handles things like the range issue Gavin mentions in a pretty slick way. It also handles auto generating appropriate legends and just generally has a more polished feel in my opinion out of the box with less manual manipulation.

library(ggplot2)

#Sample data
dat <- data.frame(dens = c(rnorm(100), rnorm(100, 10, 5))
                   , lines = rep(c("a", "b"), each = 100))
#Plot.
ggplot(dat, aes(x = dens, fill = lines)) + geom_density(alpha = 0.5)

enter image description here

Solution 3

Adding base graphics version that takes care of y-axis limits, add colors and works for any number of columns:

If we have a data set:

myData <- data.frame(std.nromal=rnorm(1000, m=0, sd=1),
                     wide.normal=rnorm(1000, m=0, sd=2),
                     exponent=rexp(1000, rate=1),
                     uniform=runif(1000, min=-3, max=3)
                     )

Then to plot the densities:

dens <- apply(myData, 2, density)

plot(NA, xlim=range(sapply(dens, "[", "x")), ylim=range(sapply(dens, "[", "y")))
mapply(lines, dens, col=1:length(dens))

legend("topright", legend=names(dens), fill=1:length(dens))

Which gives:

enter image description here

Solution 4

Just to provide a complete set, here's a version of Chase's answer using lattice:

dat <- data.frame(dens = c(rnorm(100), rnorm(100, 10, 5))
                   , lines = rep(c("a", "b"), each = 100))

densityplot(~dens,data=dat,groups = lines,
            plot.points = FALSE, ref = TRUE, 
            auto.key = list(space = "right"))

which produces a plot like this: enter image description here

Solution 5

That's how I do it in base (it's actually mentionned in the first answer comments but I'll show the full code here, including legend as I can not comment yet...)

First you need to get the info on the max values for the y axis from the density plots. So you need to actually compute the densities separately first

dta_A <- density(VarA, na.rm = TRUE)
dta_B <- density(VarB, na.rm = TRUE)

Then plot them according to the first answer and define min and max values for the y axis that you just got. (I set the min value to 0)

plot(dta_A, col = "blue", main = "2 densities on one plot"), 
     ylim = c(0, max(dta_A$y,dta_B$y)))  
lines(dta_B, col = "red")

Then add a legend to the top right corner

legend("topright", c("VarA","VarB"), lty = c(1,1), col = c("blue","red"))
Share:
194,909
pasta
Author by

pasta

php - c++ - delphi

Updated on November 03, 2020

Comments

  • pasta
    pasta over 3 years

    I would like to overlay 2 density plots on the same device with R. How can I do that? I searched the web but I didn't find any obvious solution.

    My idea would be to read data from a text file (columns) and then use

    plot(density(MyData$Column1))
    plot(density(MyData$Column2), add=T)
    

    Or something in this spirit.

  • Gavin Simpson
    Gavin Simpson almost 13 years
    +1 You might need something slightly more complex when the two densities have different ranges and the second curve doesn't fit within the plot limits. Then you can compute the densities before plotting, and compute an appropriate ylim using range(dens1$y, dens2$y) where dens1 and dens2 are the objects containing the two density estimation objects. Use this ylim in the call to plot().
  • nullglob
    nullglob almost 13 years
    You will probably also want to distinguish between the two lines. Setting the line width (lwd), line type (lty) or the line color (col) should help here. At that point, you might also consider adding a legend, using legend()
  • Roman Luštrik
    Roman Luštrik almost 13 years
    @Gavin If the OP is reading from a file, I would construct an elaborate function that would read in data (sapply, lapply), find ranges of all data sets, set the default range to the max range of all and then plot (lines) the densities.
  • cbeleites unhappy with SX
    cbeleites unhappy with SX almost 13 years
    The OP's data.frame needs to be molten to long form first: ggplot (melt (MyData), mapping = aes (fill = variable, x = value)) + geom_density (alpha = .5)
  • Marek
    Marek almost 13 years
    Without creating new data.frame: densityplot(~rnorm(100)+rnorm(100, 10, 5), plot.points=FALSE, ref=TRUE, auto.key = list(space = "right")). Or for OP data densityplot(~Column1+Column2, data=myData).
  • Erik Aronesty
    Erik Aronesty almost 11 years
    Nice plot. What's "dat2" ... ? what's "melt" (command not found) ?
  • Chase
    Chase almost 11 years
    @ErikAronesty - you're guess is as good as mine at this point, I answered this two years ago! I speculate that I had another object named dat in my environment so named it dat2...the simulated data I provide works as advertised though. the melt() command comes from package reshape2. Back in 2011, reshape2 was automatically loaded when ggplot2 was loaded, but that's no longer the case so you need to do library(reshape2) separately.
  • daisy
    daisy about 7 years
    I like this example, but if you have columns of data that includes NA values it does not work. I'm unsure how to modify the code, but this would be useful
  • Karolis Koncevičius
    Karolis Koncevičius about 7 years
    @daisy change this line dens <- apply(myData, 2, density) to dens <- apply(myData, 2, density, na.rm=TRUE) and it should work.