1
votes

This answer shows how to use groups and panel.superpose to display overlapping histograms in the same panel, assigning different colors to each histogram. In addition, I want to give each histogram a different border color. (This will allow me to display one histogram as solid bars without a border, overlayed with a transparent, all-border histogram. The example below is a little different for the sake of clarity.)

Although it's possible to use border= to use different border colors in the plot, they are not assigned to groups as fill colors are with col=. If you give border= a sequence of colors, it seems to cycle through them one bar at at time. If the two histograms overlap, the effect is a bit silly (see below).

Is there a way to give each group a specific border color?

# This illustrates the problem: Assignment of border colors to bars ignores grouping:

# make some data
foo.df <- data.frame(x=c(rnorm(10),rnorm(10)+2), cat=c(rep("A", 10),rep("B", 10)))

# plot it
histogram(~ x, groups=cat, data=foo.df, ylim=c(0,75), breaks=seq(-3, 5, 0.5), lwd=2,
          panel=function(...)panel.superpose(..., panel.groups=panel.histogram, 
                                             col=c("transparent", "cyan"), 
                                             border=c(rep("black", 3), rep("red", 3))))

Note that you can't just count how many bars there are in each group and provide those numbers to rep in the border setting. If the two histograms overlap, at least one of the histograms will use two border colors.

overlapping histograms showing cycling border colors

(It's the panel.superpose code that places the groups on the same panel and that assigns the colors. I don't have a deep understanding of it.)

1

1 Answers

3
votes

panel.histogram() doesn't have a formal groups= argument, and if you examine its code, you'll see that it handles any supplied groups= argument differently and in a less standard way than panel.*() functions that do. The upshot of that design decision is that (as you've found) it's not in general easy to pass in to it vectors of graphical parameters specifying per-group appearance

As a workaround, I'd suggest using latticeExtra's +() and as.layer() functions to overlay a number of separate histogram() plots, one for each group. Here's how you might do that:

library(lattice)
library(latticeExtra)

## Split your data by group into separate data.frames
foo.df <- data.frame(x=c(rnorm(10),rnorm(10)+2), cat=c(rep("A", 10),rep("B", 10)))
foo.A <- subset(foo.df, cat=="A")
foo.B <- subset(foo.df, cat=="B")

## Use calls to `+ as.layer()` to layer each group's histogram onto previous ones  
histogram(~ x, data=foo.A, ylim=c(0,75), breaks=seq(-3, 5, 0.5), 
          lwd=2, col="transparent", border="black") +
as.layer(
histogram(~ x, data=foo.B, ylim=c(0,75), breaks=seq(-3, 5, 0.5), 
          lwd=2, col="cyan", border="red") 
)

enter image description here