2
votes

I'm using ggplot (v1.0.1) to plot histograms with bar fill mapped to a binary State factor and using position = "dodge". The histograms are facetted by a second Group factor. When one level of the State factor is absent from a group, the plot for that facet differs from those where both levels are present. The following toy example illustrates this:

set.seed(1234)
states <- c("Alive", "Dead")
dat <- data.frame(Group = rep(LETTERS[1:2], each=100), 
              Measure = rnorm(200, 50, 10),
              State = c(rep(states, 50), rep("Alive", 100)))

ggplot() +
  geom_histogram(data=dat, aes(x=Measure, fill=State), 
                 position="dodge", binwidth=5) +
  facet_wrap(~ Group)

default behaviour with level dropped from facet B

What I would like is for the bars in the facet for Group B to have the same width and relative position as those for Group A. I thought facet_wrap(~ Group, drop = FALSE) would accomplish this but it doesn't seem to have any effect. The following work-around achieves the desired plot:

dat <- rbind(dat, data.frame(Group="B", Measure=50, State=NA))
ggplot() +
  geom_histogram(data=dat, aes(x=Measure, fill=State), 
                 position="dodge", binwidth=5) +
  scale_fill_discrete(na.value = NA) +
  facet_wrap(~ Group)

work-around to give same bin width and position in facets

But I'm sure I must be missing a ggplot option that would accomplish this without having to hack the data.

1
ggplot is generally very good at plotting the data in your data frame, I'm not sure that I'd consider making your data frame better match what you want to plot "hacking the data". tidyr has the complete() function for just such a transformation.Gregor Thomas
In the strict sense, your plot is not a histogram. Instead of using position_dodge, I'd use alpha transparency or another faceting dimension.Roland
@Gregor thanks for the tip about the tidyr functionmichael

1 Answers

4
votes

The short answer is NO; there is unfortunately no ggplot option that can achieve this for you. There are several workarounds.

The first and probably easiest option you have already found, adding NA's.

The second option is to manually adjust the width of the bars, like in the first answer to this question.

The third option is taken from the suggestion @Roland: don't "dodge" but use transparency:

ggplot() +
  geom_histogram(data=dat, aes(x=Measure, fill=State), 
                 position=position_identity(), binwidth=5, alpha=0.5) +
  facet_wrap(~ Group) +
  #change the colors and background, to improve visibility
  scale_fill_manual(values=c("red","blue")) +
  theme(panel.background = element_rect(fill = "transparent",colour = "black"))

Will give you this graph:

ggplot histogram with transparency

Personally I find it hideous.