neversaint
neversaint

Reputation: 64054

How to plot multiple normal distributions in 1 figure in R

I have a data that gives the mean and SD:

#info mean sd
info1 20.84 4.56
info2 29.18 5.41
info3 38.90 6.22

Actually there are more than 100 lines of this. How can I plot normal distributions for each one of the line in one figure given the above data?

Upvotes: 4

Views: 13359

Answers (2)

Tyler Rinker
Tyler Rinker

Reputation: 109984

Again a dollar short and a day late. Chase has a very thorough response. Here's my crack at it:

dat <- read.table(text="info  mean  sd
info1 20.84 4.56
info2 29.18 5.41
info3 38.90 6.22", header=T)

dat <- transform(dat, lower= mean-3*sd, upper= mean+3*sd)

plot(x=c(min(dat$lower)-2, max(dat$upper)+2), y=c(0, .25), ylab="", 
    xlim=c(min(dat$lower)-2, max(dat$upper)+2), xlab="", 
    axes=FALSE, xaxs = "i", type="n")
box()

FUN <- function(rownum) {
    par(new=TRUE)
    curve(dnorm(x,dat[rownum, 2], dat[rownum, 3]),
        xlim=c(c(min(dat$lower)-2, max(dat$upper)+2)), 
        ylim=c(0, .22),
        ylab="", xlab="")
}

lapply(seq_len(nrow(dat)), function(i) FUN(i))

enter image description here

Upvotes: 6

Chase
Chase

Reputation: 69211

Depending on how large N truly gets, you may want to split this up over a set of multiple charts. But, here's the basic approach. First, you need to generate some random data according to your mean and sd. I chose 1000 random points, you can adjust as necessary. Next, set up a blank plot with the appropriate dimensions, then use lines and density to add the data. I used a for loop because it provided a nice way to specify the linetype for each data point. Finally, add a legend at the end:

dat <- read.table(text = "info mean sd
info1 20.84 4.56
info2 29.18 5.41
info3 38.90 6.22
", header = TRUE)

densities <- apply(dat[, -1], 1, function(x) rnorm(n = 1000, mean = x[1], sd = x[2]))
colnames(densities) <- dat$info

plot(0, type = "n", xlim = c(min(densities), max(densities)), ylim = c(0, .2))
for (d in 1:ncol(densities)){
  lines(density(densities[, d]), lty = d)
}
legend("topright", legend=colnames(densities), lty=1:ncol(densities))

enter image description here

Or, use ggplot2 which can have lots of benefits, namely it will specify reasonable xlim and ylim values for you automagically, and do sensible things with the legend without much fuss.

library(reshape2)
library(ggplot2)
#Put into long format
densities.m <- melt(densities)
#Plot
ggplot(densities.m, aes(value, linetype = Var2)) + geom_density()

enter image description here

Upvotes: 8

Related Questions