Search code examples
rggplot2facet-grid

r: facet_grid order not following levels with plotmath


I have the following example:

library(latex2exp)
library(ggplot2)

#Simulate some data
datplot <- data.frame(
  bta = rep(c("b0", "b1", "b1-b0"), each = 100),
  electrode = rep(c("Fz","Cz","Pz"), times = 100),
  value = runif(300,-2,5)
)

#Add some specifics that will be used in the following code
stdev <- c(10, 6, 5, 8)
col <- c("#004d8d", "#cc2701", "#e5b400")
time <- '225'

Now, following suggestions from other StackOverflow posts like this or this I set the appropriate levels of the factor to set the desired order.

#Set the levels and the labels in plotmath
datplot$bta <- factor(datplot$bta, levels=c("b0","b1","b1-b0"),labels=c("b0" = TeX(r"{$\beta_0\cdot x\; (x=0)$}"),
                                                                        "b1" = TeX(r"{$\beta_0+\beta_1\cdot x\; (x=1)$}"),
                                                                        "b1-b0" = TeX(r"{$\beta_0+\beta_1\cdot x-\beta_0= \beta_1\cdot x\; (x=1)$}")))

Incidentally, I add some other annotations that will be used in a geom_rect, that refers to a particular reference important in my original dataset, but that we could ignore here.

#Add some annotations dataframe to add a reference frame with geom_rect later
annotations <- data.frame(
  xmin = c(0,0,-0.1*min(stdev)),
  xmax = c(0,0,0.1*max(stdev)),
  ymin = c(0,0,0),
  ymax = c(0,0,Inf),
  bta = c('beta[0] %.% x ~ ~(x * {\n    phantom() == phantom()\n} * 0)',
          'beta[0] + beta[1] %.% x ~ ~(x * {\n    phantom() == phantom()\n} * 1)',
          'beta[0] + beta[1] %.% x - beta[0] * {\n    phantom() == phantom()\n} * beta[1] %.% x ~ ~(x * {\n    phantom() == phantom()\n} * 1)')
)

And I finally plot the ggplot object with the following code.

p1 <- datplot %>%
  ggplot(mapping = aes(x=value, y=factor(electrode, levels = c('Fz','Cz','Pz')), group = electrode, color = electrode)) +
  scale_y_discrete() +
  geom_rect(data=annotations, inherit.aes = FALSE, mapping = aes(
    ymin = ymin, ymax = ymax, xmin = xmin, xmax = xmax), fill = "black", alpha = 0.1) +
  geom_density_ridges(scale = -0.5, alpha=0.5,
                      quantile_lines = TRUE, 
                      quantiles = c(0.025, 0.5, 0.975), 
                      vline_color = alpha("white", 0.3), 
                      aes(fill = electrode)) +
  facet_grid(~bta, labeller=label_parsed) +
  scale_color_manual(values = col, breaks = c("Fz", "Cz", "Pz")) +   
  scale_fill_manual(values = col, breaks = c("Fz", "Cz", "Pz")) +
  labs(title=sprintf('%s ms.',time)) +
  ylab("Electrode") +
  xlab('(Signal (µV) Posteriors)') +
  theme_light() +
  theme(axis.text = element_text(size = 14)) +
  theme(axis.title = element_text(size = 16)) +
  theme(plot.title = element_text(size = 20)) +
  coord_flip(xlim = c(-8, 8), ylim = c(0.4,3.05), expand = FALSE, clip = "on")
p1

Unfortunately, the order is wrong, according to the previously set levels, the third column should be the second and the second the third. In other words, the one with the geom_rect grey bar should go last, but somehow it doesn't respect the order from the previous levels argument as you can see in the image:

image output

I am sure this is all about plotmath because it has no problem when I enter simpler labels to the facet_grid. I have also tried with facet_wrap and the problem persists.


Solution

  • You need to set the same levels for all elements in all your data frames. In this case, your annotations$bta is not a factor with the same levels.

    ## confirm first
    all(annotations$bta %in% as.character(datplot$bta))
    ## fix
    annotations$bta <- factor(annotations$bta, levels = levels(datplot$bta))
    

    ggplot2 with factors fixed

    FYI, it seems perhaps a little fragile to use TeX(..) in one location and hand-coded strings in another. I suggest defining the Tex(..) labels in one place and use that in both datplot and annotations. That way, if there's ever a change in TeX's orientation (e.g., an extra space), your code will still work as intended.