Skip to content

lattice barchart with "negative" bars

4 messages · Luis Torgo, Deepayan Sarkar

#
Dear all,

I'm trying to use the lattice barchart function to obtain a bar plot of a 
variable for different values of two factors. The thing I'm trying to do is 
something like this:
My problem is that the column MyVar has some negative values and I would like 
them to be represented as bars stacking down from zero instead of what the 
function does that is finding the minimum value and then stacking all bars 
from this minimum value up. I've looked into the the help pages and I saw no 
way to go around this behaviour. Is there an easy way to get these "negative" 
bars?

Thanks,
Luis
#
On Tuesday 10 December 2002 06:11 am, Luis Torgo wrote:
No, I don't think so (short of using a modified panel.barchart, which should 
be relatively easy -- panel.barchart essentially has just 3 lines of code). 
But this seems very reasonable thing to want, so I'll add an option for this.

You could also use xyplot with type = "h", but that will give you lines 
instead of bars.

Deepayan
#
On Tuesday 10 December 2002 14:30, Deepayan Sarkar wrote:

            
Thank you for your help. You are right it is easy to adapt panel.barchart to 
perform what I wanted. As such, while you do not add an option for that, I've 
took the liberty to create my version of panel.barchart to solve the problem 
temporarily. I herein include it together with a simple example use, in case 
somebody has the same problem as me.

The function works almost fine. The only problem I was not able to get around 
is the zero value reference line I want to draw in the case of horizontal 
bars. I've used the grid.lines function. It works fine for vertical bars, but 
it doesn't work for horizontal bars...

Luis Torgo


# Adapted from the code of panel.barchart by Deepayan Sarkar
my.panel.barchart <- function (x, y, box.ratio = 1, horizontal = TRUE, col = 
bar.fill$col, 
    ...) 
{
    x <- as.numeric(x)
    y <- as.numeric(y)
    bar.fill <- trellis.par.get("bar.fill")
    if (horizontal) {
        height <- box.ratio/(1 + box.ratio)
        grid.lines(x=0,y=unit(c(0,1),"npc"),default.units="native")
        for (i in seq(along = x))
          if (x[i] >= 0)
            grid.rect(gp = gpar(fill = col), y = y[i], x = 0,
                      height = height, width = y[i] - 0, 
                      just = c("left", "centre"), default.units = "native")
          else
            grid.rect(gp = gpar(fill = col), y = y[i], x = x[i],
                      height = height, width = 0 - x[i], 
                      just = c("left", "centre"), default.units = "native")
    }
    else {
        width <- box.ratio/(1 + box.ratio)
        grid.lines(x=unit(c(0,1),"npc"),y=0,default.units="native")
        for (i in seq(along = y))
          if (y[i] >= 0)
            grid.rect(gp = gpar(fill = col), x = x[i], y = 0,
                      height = y[i] - 0, width = width, 
                      just = c("centre", "bottom"), default.units = "native")
          else
            grid.rect(gp = gpar(fill = col), x = x[i], y = y[i],
                      height = 0 - y[i], width = width, 
                      just = c("centre", "bottom"), default.units = "native")
    }
}

# Example using the function

my.data <- 
data.frame(var=c(34,-10,25,-40),season=c('s','w','s','w'),site=c('A','A','B','B'))

barchart(var ~ season | site, data=my.data, panel="my.panel.barchart")
#
On Tuesday 10 December 2002 12:15 pm, Luis Torgo wrote:
This seems to need x = c(0,0). It's slightly odd that this works in the other 
case. In any case, 

          panel.abline(v = 0) ## correspondingly, h = 0 below

might be a more elegant solution.
^^^^^^^^^^^^^^^^
Typo here, should be                     width = x[i] - 0,