[R] Overlying a Normal Dist in a Barplot

Marc Schwartz MSchwartz at mn.rr.com
Sat Jul 9 04:38:23 CEST 2005


On Fri, 2005-07-08 at 21:58 -0400, Gabor Grothendieck wrote:
> On 7/8/05, Bret Collier <bret at tamu.edu> wrote:
> > R-Users,
> > Hopefully someone can shed some light on these questions as I had
> > little luck searching the archives (although I probably missed something
> > in my search due to the search phrase).  I estimated multinomial
> > probabilities for some count data (number successful offspring) ranging
> > from 0 to 8 (9 possible response categories).  I constructed a barplot
> > (using barplot2) and I want to "overlay" a normal distribution on the
> > figure (using rnorm (1000, mean, sd)).  My intent is to show that using
> > a mean(and associated sd) estimated from discrete count data may not be
> > a valid representation of the distribution of successful offspring.
> > 
> > Obviously the x and y axes (as structured in barplot2) will not be
> > equivalent for these 2 sets of information and this shows up in my
> > example below.
> > 
> > 1)  Is it possible to somehow reconcile the underlying x-axis to the
> > same scale as would be needed to overly the normal distribution (e.g.
> > where 2.5 would fall on the normal density, I could relate it to 2.5 on
> > the barplot)?  Then, using axis (side=4) I assume I could insert a
> > y-axis for the normal distribution.
> > 
> > 2)  Is lines(density(x)) the appropriate way to insert a normal
> > distribution into this type of figure?  Should I use 'curve'?
> > 
> > If someone could point me in the right direction, I would appreciate
> > it.
> > 
> > TIA, Bret
> > 
> > Example:
> > 
> > testdata
> > 0    0.196454948
> > 1    0.063515510
> > 2    0.149187592
> > 3    0.237813885
> > 4    0.282127031
> > 5    0.066469719
> > 6    0.001477105
> > 7    0.001477105
> > 8    0.001477105
> > 
> > 
> > x<-rnorm(1000, 2.84, 1.57)
> > barplot2(testdata, xlab="Fledgling Number",
> >             ylab="Probability", ylim=c(0, 1), col="black",
> >             border="black", axis.lty=1)
> > lines(density(x))
> > 
> 
> Maybe something like this using rect and curve:
> 
> # data from your post
> testdata <- c(0.196454948, 0.06351551, 0.149187592, 0.237813885, 
>   0.282127031, 0.066469719, 0.001477105, 0.001477105, 0.001477105)
> x <- 0:9
> 
> # setup plot ranges noting max of normal density is at mean
> xrange <- range(x) + c(-0.5,+0.5)
> yrange <- range(c(testdata, dnorm(2.84, 2.84, 1.57), 0))
> plot(xrange, yrange, type = "n", xlab = "X", ylab = "Probability", xaxt = "n")
> axis(1, x)
> 
> # draw bars using rect and density using curve
> rect(x - 0.5, 0, x + 0.5, testdata, col = "lightgrey")
> curve(dnorm(x, 2.84, 1.57), min(xrange), max(xrange), add = TRUE)

Nice solution Gabor.

I had to think about this one for a bit, and think I may have it using
barplot[2]():

> testdata
  V1          V2
1  0 0.196454948
2  1 0.063515510
3  2 0.149187592
4  3 0.237813885
5  4 0.282127031
6  5 0.066469719
7  6 0.001477105
8  7 0.001477105
9  8 0.001477105


# Change 'space = 0' so that bars are adjacent to each other
# This also puts each bar center at seq(0.5, 8.5, 1)
mp <- barplot2(testdata[, 2], xlab="Fledgling Number", 
               ylab="Probability", ylim=c(0, .3),  
               axis.lty = 1, names.arg = testdata[, 1],
               space = 0)

> mp
      [,1]
 [1,]  0.5
 [2,]  1.5
 [3,]  2.5
 [4,]  3.5
 [5,]  4.5
 [6,]  5.5
 [7,]  6.5
 [8,]  7.5
 [9,]  8.5
 
x <- testdata[, 1]

# Now do the curve and shift the mean by +0.5
# To coincide with the bar centers
curve(dnorm(x, 2.84 + 0.5, 1.57), add = TRUE)


I think that does it.

HTH,

Marc Schwartz




More information about the R-help mailing list