Search code examples
rlatticer-grid

Why do grid lines in lattice plot cover *some* but not all data points?


I am trying to create a graph using the lattice package in R. I am aware of other existing packages but would like to use lattice if possible.

In order to add errorbars to a grouped xyplot, I adopted Deepayan Sarkars solution which I found here (code below).

It works fine unless I try to add gridlines to the plot. The grid lines cover some of the data points but not all of them. Does anybody understand why this is and how it can be avoided? I would like the grid to be drawn in the background.

library(lattice)

# prepare sample data -----------------------------------------------
singer.split <- with(singer,
       split(height, voice.part))
singer.ucl <- sapply(singer.split,
         function(x) {
           st <- boxplot.stats(x)
           c(st$stats[3], st$conf)})

singer.ucl <- as.data.frame(t(singer.ucl))
names(singer.ucl) <- c("median", "lower", "upper")
singer.ucl$voice.part <- factor(rownames(singer.ucl),
         levels = rownames(singer.ucl))

singer.ucl$voice=factor(rep(c(1,2),4))
singer.ucl$range=factor(rep(c("Bass","Tenor","Alto","Soprano"),each=2))

# custom panel functions ----------------------------------------------
prepanel.ci <- function(x, y, ly, uy, subscripts, ...) {
  x <- as.numeric(x)
  ly <- as.numeric(ly[subscripts])
  uy <- as.numeric(uy[subscripts])
  list(ylim = range(y, uy, ly, finite = TRUE))}

panel.ci <- function(x, y, ly, uy, subscripts, pch = 16, col.line =
                       'black', ...) {
  x <- as.numeric(x)
  y <- as.numeric(y)
  ly <- as.numeric(ly[subscripts])
  uy <- as.numeric(uy[subscripts])
  panel.abline(v=1:2, col = "black", lwd = 2)
  panel.arrows(x, ly, x, uy, col = col.line,
               length = 0.25, unit = "native",
               angle = 90, code = 3)
  panel.xyplot(x, y, pch = pch, col.line = col.line, ...)}

# plot---------------------------------------------------------------
xyplot(median ~ voice,
       groups=range,
       data=singer.ucl,
       ly = singer.ucl$lower,
       uy = singer.ucl$upper,
       prepanel = prepanel.ci,
       panel = panel.superpose,
       panel.groups = panel.ci,
       type="p", pch = 19)

On my machine (macOS, R.3.4.0, lattice_0.20-35), the red point is in front of the black grid line and all other points are being covered:

Red point in front of grid but other points in background

Help would be greatly appreciated.

Thank you,

Konrad


Solution

  • There is a +.trellis function in package:latticeExtra authored by Sarkar and Andrews. It handles all the complex grid calls behind the scenes, as it were. If you make a slight variant of your panel.ci function that has the abline call commented out, and name it panel.ci2, you can over-write an existing plot-object.

    library(latticeExtra)  # perhaps need to install first
     my.plot <- xyplot(median ~ voice,
            groups=range,
            data=singer.ucl,
            ly = singer.ucl$lower,
            uy = singer.ucl$upper,
            prepanel = prepanel.ci,
            panel = panel.superpose,
            panel.groups = panel.ci,
            type="p", pch = 19)
     myplot2 <- my.plot + xyplot(median ~ voice,
                                         groups=range,
                                         data=singer.ucl,
                                         ly = singer.ucl$lower,
                                         uy = singer.ucl$upper,
    
                                         panel = panel.superpose,
                                         panel.groups = panel.ci2,
                                         type="p", pch = 19)
     png(); print( myplot2) ; dev.off()
    

    enter image description here

    A note on debugging. I first tried just using panel.xyplot in the place that now has panel.ci2 and only the solid points appeared in front, which made me realize that I needed the arrows in the panel function as well. I think the plot looks a lot better with an abline-call using lty = 3 and lwd=0.5.