[R] Back-to-back graph with lattice package

David Winsemius dwinsemius at comcast.net
Sat Oct 31 18:35:04 CET 2009

On Oct 31, 2009, at 4:16 AM, Erik Svensson wrote:

> Hi,
> Thank you for your reply.
> I have looked into the epicalc package already and it will not help me
> this time.
> I realize that I wasn't clear enough. In my example I want to relate
> all my data to Country, i.e. the distribution of Hair,  Eye color, Sex
> (they are dichotomous in my example) and Age should all be related  
> to each of
> the five countries.
> Pyramid in epicalc can't be used for relating e.g.Hair with Country,
> and I can't get the labels for countries. Furthermore, I want all the
> data in the nice panels of lattice as one single plot, which will  
> occupy
> rather little space.
> So, yes, I'm looking for a work-around.
> When I make barcharts or dotplots from my categorical data, I first
> need make a table. One work-around could be to  e.g. in the Sex-column
> of the table multiply the values for male by '-1' to get negative
> values, Then the bars or dots for male would go to the left and the
> female bars go to the right. Unfortunately, I don't know how do these
> calculations and if the plot looks good.

I have not found a worked example using lattice using either r-search,  
r-graph-gallery,  or flipping through Sarkar's Lattice book. I thought  
you might need to use base graphics using layout() with a 4 x 5  
specification,  and separately plot pyramid type plots within each  
subsection of a page. (I suppose there are a few people who might be  
able to create a panel function that would create a back-to-back plot  
within Lattice, but I have sufficient difficulty doing ordinary  
Lattice plots, that this is surely beyond my ability.) Regarding the  
concern for the dichotomous variables, I assume that a single pair of  
vectors (one for each country with Hair=="brown" and another for  
Hair=="blond") ought to give back to back plots when using pyramid or  
pyramid-like functions.


Thinking the set up might be like this if you were putting the age- 
pyramid on top:

layout(matrix(1:20, 4, 5, byrow=TRUE), widths = rep(1, 5), heights =  

Experimenting with this theory and the example in epicalc:::pyramid, I  
commented out all the par settings in pyramid, defining the result as  
n.pyramid and tried:

 > layout(matrix(1:4, 2,2, byrow=TRUE) heights=c(1,1), widths=c(1,1))
 > n.pyramid(age, sex)
 > n.pyramid(age, sex)

The results were a bit surprising to me (two calls filled up 4  
segments) because I'm not an ace programmer. However, they may point  
the way to a base-graphics solution with further effort. Obviously the  
author of pyramid (Chongsuvivatwong) knows more about layout() and  
par() than I, and one (or more) of the lines I commented out was  
essential for setting up the plot (most probably the mfrow=c(1,2) ).  
You could emulate this approach by adjusting the new layout to be 10 x  
4 and sequentially plotting 20 graphs and setting the main titles = "".

  #par(mfrow = c(1, 2))
     #old.par.mai <- c(0.95625, 0.76875, 0.76875, 0.39375)
     #left.par.mai <- old.par.mai
     #right.par.mai <- c(old.par.mai[1], old.par.mai[4], old.par.mai[3],
      #   old.par.mai[2])
      #-------code to calculate ranges
    # par(mai = left.par.mai)
      #-------code to plot negative direction barplot
    # par(mai = right.par.mai)
      #-------code to plot positive direction

    # par(mfrow = c(1, 1)) # these just restore the graphics device to  
its prior state
    # par(mai = old.par.mai)

(attached the output pdf
-------------- next part --------------
A non-text attachment was scrubbed...
Name: n.pyramid.pdf
Type: application/pdf
Size: 384272 bytes
Desc: not available
URL: <https://stat.ethz.ch/pipermail/r-help/attachments/20091031/16432f5b/attachment-0002.pdf>
-------------- next part --------------
  file although it may not make it through the server.)

> Erik
> 2009/10/30 David Winsemius <dwinsemius at comcast.net>:
>> On Oct 30, 2009, at 9:11 AM, Erik Svensson wrote:
>>> Hi,
>>> I am an [R] and lattice beginner.
>>> I an doing an epidemiological study and want to present my data in a
>>> condensed and clear manner as possible.
>>> The example below is fake, but representative for the the data I  
>>> want to
>>> show.
>>> I have a data frame with different categorical data and one column  
>>> of
>>> numerical data:
>>> Country, Hair, Eyes, Sex, Age
>>> sweden, blond, blue, male, 25
>>> sweden, dark, brown, female, 30
>>> denmark, dark, blue, male, 22
>>> denmark, blond, blue, female 33
>>> norway, dark, blue, female, 21
>>> norway, blond, blue, male, 31
>>> finland, dark, blond, male, 43
>>> island, blond, blue, female, 40
>>> ...and so on for 300 rows...
>>> Country <- as.factor(rep(c("Sweden", "Denmark", "Norway", "Finland",
>>> "Iceland","Sweden", "Denmark", "Norway", "Finland","Sweden" ),50))
>>> Hair <- as.factor(rep(c("blond",  "dark", "blond", "dark",  
>>> "blond"),100))
>>> Eyes <- as.factor(rep(c("blue",  "blue", "blue", "brown"),125))
>>> Sex <- as.factor(rep(c("male",  "female", "female", "male"),125))
>>> Age <- rep(c(1:20, 1:100, 76:80),4)
>>> Country has 5 levels, Age has many.
>>> Hair, Eyes, and Sex have two levels each
>>> I want to do one lattice graph with 5 columns of panels with these
>>> descriptive data.
>>> I would prefer to use the lattice barchart or the corresponding
>>> dotplot with lines (except for the Age panel)
>>> The  Age panel and probably the Country panel I think I can solve  
>>> myself:
>>>        barchart(Country)  # This only gives one panel, though...
>>>        densityplot(~ Age|Country,  layout=c(1,5),  
>>> xlim=c(0,100),scales =
>>> list(y=list (relation="free")))
>>> But, for the dichotomous variables Hair, Eyes, and Sex columns I  
>>> would
>>> like to have a bihistogram aka back-to-back aka age-sex-pyramid
>>> solution.
>>> I want all bars to be horizontal, the names of the countries to the
>>> left on the y-axis.
>>> I would also like to sort the country names according to a list of  
>>> their
>>> names.
>>> For the back-to-back graph  I have only managed to get two panels  
>>> per
>>> column instead of one:
>>>        barchart(table(Country, Hair),groups=FALSE)
>> My suggestion would be to look for a worked solution.
>> library(sos)
>> ???pyramid
>> The two I found upon taking my own advice are pyramid in epicalc and
>> pyramid.plot in plotrix. Experimenting shows that the epicalc pyramid
>> solution is more flexible and requires less pre-processing of the  
>> data.
>> library(epicalc)
>> data(Oswego)
>> use(Oswego)
>> pyramid(age, sex)
>> # ... and on your data:
>> pyramid(Age, Hair)    # ... seems to deliver the requested plot.
>>> How can I do all this? Is it possible at all?
>> library(fortunes)
>> fortune("Only how")
>>> Erik Svensson
>> --
>> David Winsemius, MD
>> Heritage Laboratories
>> West Hartford, CT

David Winsemius, MD
Heritage Laboratories
West Hartford, CT

More information about the R-help mailing list