Search code examples
rggplot2dplyrfacet-grid

Fixing the order of facets in ggplot when using dplyr to transform data to long form


I got help here yesterday to create a facet grid of multiple columns. This yielded a large grid containing 8*5 plots. The code creates a combination of plot for various Outcomes * Responses. For example (Outcome1 * Response1, Outcome1 * Response2, Outcome3 * Response1, Outcome2 * Response1 and so on).

I have pasted the code below.

plot1 <- ancestralmeansindex %>%
gather(var1, value1, bicepind:wcind) %>%
gather(var2, value2, mmois:mpfat) %>%
ggplot(aes(x = value1, y = value2)) + 
geom_point(color='blue') +
geom_smooth(method = "lm", se = FALSE) +
facet_grid(var2 ~ var1, scales = "free", switch = "both",
         labeller = as_labeller(c(mmois = "Water (gms)",
                                  mkcal = "Caloric Intake",
                                  mprot = "Protein (gms)",
                                  mcarb = "Carb (gms)",
                                  mtfat = "Total Fat (gms)",
                                  msfat = "Saturated Fat (gms)",
                                  mmfat = "Mono S.Fat (gms)",
                                  mpfat = "Poly US.Fat (gms)",
                                  bicepind = "Bicep",
                                  tricepind = "Tricep",
                                  subind = "Subscapular",
                                  supind = "Suprailiac",
                                  weightind = "Weight",
                                  wcind = "Waist Circum"))) +
  labs(title = "Regression Plot Matrix of Mean Dietary Values with    Index Change 1", x = NULL, y = NULL) +
theme_bw() +
theme(strip.placement = "outside",
    strip.background = element_blank())
ggsave("Regression Plot 1.pdf", width = 210, height = 297, units = "mm", plot1) 

This gives a very neat grid of all the possible combinations mentioned in the code. However, the graph prints the plots in alphabetical order (as it is reflected in the labeller/data). I would like to change this order for both var2 and var1.

I read in the help that this problem can be solved by assigning factor levels and choosing a given order. For example, this solution Fixing the order of facets in ggplot

How do I assign factor levels to variables that have been converted to long form by dplyr? Can this be done? Is there another solution?

Edit1 I tried the solution below, but I am running into an error. Reproducible example below.

set.seed(1)
dat <- data.frame(
  Outcome1 = sample(1:10),
  Outcome2 = sample(11:20),
  Outcome3 = sample(21:30),
  Response1 = sample(31:40),
  Response2 = sample(41:50),
  Response3 = sample(51:60)
)

dat %>%
  gather(var1, value1, Outcome1:Outcome3) %>%
  mutate(var1, recode("Outcome1" = "Bicep",
                      "Outcome2" = "Tricep",
                      "Outcome3" = "Subscapular")) %>%
  factor(var1, levels = c("Bicep",
                          "Tricep",
                          "Subscapular")) 
gather(var2, value2, Response1:Response3) %>% 
  mutate(var2, recode("Response1" = "Water (gms)", 
                      "Response2" = "Caloric Intake",
                      "Response3" = "Protein (gms)")) %>%
  factor(var2, levels = c("Water (cms)", 
                          "Caloric Intake",
                          "Protein (gms)")) %>%
  ggplot(aes(x = value1, y = value2)) + 
  geom_point(color='blue') +
  geom_smooth(method = "lm", se = FALSE) +
  facet_grid(var2 ~ var1, scales = "free", switch = "both",
             labeller = as_labeller(c(mmois = "Water (gms)",
                                      mkcal = "Caloric Intake",
                                      mprot = "Protein (gms)",
                                      bicepind = "Bicep",
                                      tricepind = "Tricep",
                                      subind = "Subscapular"))) +
  labs(title = "Regression Plot", x = NULL, y = NULL) +
  theme_bw() +
  theme(strip.placement = "outside",
        strip.background = element_blank())


Error in factor(., var1, levels = c("Bicep", "Tricep", "Subscapular",  : 
  object 'var1' not found

Error in gather(var2, value2, Response1:Response3) : 
  object 'var2' not found

Solution

  • Yes! It can be done. Use dplyr mutate to recode your var1 and var2 variables, then use factor to ensure the levels are in the right order. Then you won't need to use the labeler. Thanks to your reproducible example I was able to test my solution and fix the code!

     dat %>%
      gather(var1, value1, Outcome1:Outcome3) %>%
      mutate(var1 = recode(var1, "Outcome1" = "Bicep",
                          "Outcome2" = "Tricep",
                          "Outcome3" = "Subscapular")) %>%
      mutate(var1 = factor(var1, levels = c("Bicep",
                              "Tricep",
                              "Subscapular"))) %>% 
    gather(var2, value2, Response1:Response3) %>% 
      mutate(var2 = recode(var2, "Response1" = "Water (gms)", 
                          "Response2" = "Caloric Intake",
                          "Response3" = "Protein (gms)"),
              var2 = factor(var2, levels = c("Water (gms)", 
                              "Caloric Intake",
                              "Protein (gms)"))) %>%
      ggplot(aes(x = value1, y = value2)) + 
      geom_point(color='blue') +
      geom_smooth(method = "lm", se = FALSE) +
      facet_grid(var2 ~ var1, scales = "free", switch = "both") +
      labs(title = "Regression Plot", x = NULL, y = NULL) +
      theme_bw() +
      theme(strip.placement = "outside",
            strip.background = element_blank())