Violin Plot with Outliers

One solution is to define a new panel function like this:
panel.violinWithOutliers <- function(x, y, horizontal, ...) {
    panel.violin(x, y, horizontal = horizontal, ...)
    if (horizontal) {
        xs <- split(x, y)
        for (i in seq_along(xs)) {
            out <- boxplot.stats(xs[[i]])$out
            if (length(out) > 0)
                panel.points(out, rep(i, length(out)))
        }
    }
    else {
        ys <- split(y, x)
        for (i in seq_along(ys)) {
            out <- boxplot.stats(ys[[i]])$out
            if (length(out) > 0)
                panel.points(rep(i, length(out)), out)
        }
    }
}
Some examples:
library(lattice)
library(latticeExtra)
data(gvhd10) 
bwplot(Days ~ log(FSC.H), gvhd10,
       panel = panel.violinWithOutliers,
       box.ratio = 3,
       xlab = "log(Forward Scatter)", ylab = "Days Past Transplant")

bwplot(log(FSC.H) ~ Days, gvhd10,
       panel = panel.violinWithOutliers,
       horizontal = FALSE,
       box.ratio = 3,
       ylab = "log(Forward Scatter)", xlab = "Days Past Transplant")
In developing a new panel function it can be useful to start with a minimal one containing a browser() call and then experiment interactively.

Luke Tierney 2008-09-11