Search code examples
rggplot2ggforce

Function for Facet Wrap Paginate over a Factor?


I have the following table:

> tor.responsive
                  Transcript Gene.Name Genotype tpi Replicate.1 Replicate.2 Replicate.3
1  TRINITY_DN103903_c0_g1_i4 MsLHCB1.1        S   0   49.056366 144.0096979  159.051697
2   TRINITY_DN12862_c0_g1_i3   MsLHCA6        S   0   26.847656  57.1883135   62.923004
3   TRINITY_DN12910_c0_g1_i1 MsPLGG1-A        S   0    4.856194   9.7402183    9.175898
4   TRINITY_DN13552_c0_g1_i2  MsRPI3-B        S   0   26.221691  73.8716146   76.343180
5     TRINITY_DN231_c0_g1_i3  MsRPI1-B        S   0   46.041232  35.1452605   77.562641
6   TRINITY_DN38889_c0_g1_i5    MsPGK1        S   0    1.610827   0.8531732    1.914664
7     TRINITY_DN524_c0_g1_i1 MsCFBP1-A        S   0   72.722639 218.5629027  261.697935
8    TRINITY_DN5413_c1_g1_i2   MsPSBTN        S   0   99.296010 950.4469250  598.875903
9    TRINITY_DN6017_c0_g1_i3   MsTKL-1        S   0   45.140098  12.2627406   18.338120
10    TRINITY_DN610_c0_g1_i8   MsRCA-A        S   0   12.593589  33.6608395   47.774347
11  TRINITY_DN63166_c0_g1_i1  MsCRD1-B        S   0  117.637784 279.4160944  307.335882

I want to facet_wrap_paginate each plot made for Gene.Name to have individual plots in a list. Is there a way to make that a function? I am using the following code to create the plots:

tor.resp.fpkm = ggplot() + 
  geom_bar(data = tor.responsive, aes(x = tpi, y = FPKM.Mean, fill = Genotype), stat = "identity", position = 'dodge') +
  scale_fill_manual(values = c("red","blue"), guide = guide_legend(title = "Genotype")) + 
  scale_y_continuous(limit = c(NA,NA)) +
  facet_wrap_paginate(~Gene.Name, nrow = 1, ncol = 1) +
  theme_prism() + 
  theme_bw() +
  labs(x = "Time Post-Infestation (tpi)", y = "Mean FPKM", title = "") + 
  theme(axis.ticks.y = element_line(color = "black")) + guides(y = guide_prism_minor()) +
  theme(plot.title = element_text(face = "bold.italic", size = 16, family = "sans", hjust = .5)) + 
  theme(axis.title.x = element_text(size = 14)) +
  theme(axis.text.x = element_text(size = 12)) +
  theme(axis.title.y = element_text(size = 14)) +
  theme(axis.text.y = element_text(size = 12)) + 
  theme(legend.position = "none") +
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        strip.background = element_blank(),
        strip.text.x = element_blank(),
        panel.border = element_rect(colour = "black", fill = NA)) +
  theme(plot.margin = unit(c(-1.25,0.5,0.25,0.5), "cm"))

P.S - I calculate FPKM.Mean like this:

tor.responsive$FPKM.Mean = rowMeans(tor.responsive[5:7])

Data

structure(list(Transcript = c("TRINITY_DN103903_c0_g1_i4", "TRINITY_DN12862_c0_g1_i3", 
"TRINITY_DN12910_c0_g1_i1", "TRINITY_DN13552_c0_g1_i2", "TRINITY_DN231_c0_g1_i3", 
"TRINITY_DN38889_c0_g1_i5", "TRINITY_DN524_c0_g1_i1", "TRINITY_DN5413_c1_g1_i2", 
"TRINITY_DN6017_c0_g1_i3", "TRINITY_DN610_c0_g1_i8", "TRINITY_DN63166_c0_g1_i1"
), Gene.Name = c("MsLHCB1.1", "MsLHCA6", "MsPLGG1-A", "MsRPI3-B", 
"MsRPI1-B", "MsPGK1", "MsCFBP1-A", "MsPSBTN", "MsTKL-1", "MsRCA-A", 
"MsCRD1-B"), Genotype = c("S", "S", "S", "S", "S", "S", "S", 
"S", "S", "S", "S"), tpi = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L), Replicate.1 = c(49.05636627, 26.84765632, 4.856193803, 
26.22169147, 46.04123195, 1.610826506, 72.72263912, 99.29601001, 
45.14009822, 12.59358919, 117.6377843), Replicate.2 = c(144.0096979, 
57.18831345, 9.740218281, 73.87161455, 35.14526047, 0.853173159, 
218.5629027, 950.446925, 12.26274063, 33.66083948, 279.4160944
), Replicate.3 = c(159.0516969, 62.92300417, 9.175897983, 76.3431804, 
77.56264079, 1.914663635, 261.6979354, 598.8759031, 18.33811992, 
47.77434747, 307.3358824)), class = "data.frame", row.names = c(NA, 
-11L))

Solution

  • If you just want a list of plots with only one facet, you do not have to use facet_wrap_paginate. Just generate the plots directly. The workflow is as follows: first, define a function for a single plot; then, nest your dataframe based on your group variables (Gene.Name in this case); last, lapply or map the plot function across each sub-dataframe. Here is the code. Note that I also removed some unnecessary parts in your ggplot code.

    library(ggplot2)
    library(ggprism)
    library(tidyr)
    library(dplyr)
    
    plotf <- function(data, title, extrema) {
      extrema[[1L]] <- min(extrema[[1L]], 0)
      ggplot(data) + 
        geom_col(aes(x = tpi, y = FPKM.Mean, fill = Genotype), position = "dodge") +
        scale_fill_manual(values = c("S" = "red", "???" = "blue")) + # You should specify colors for each value for clarity. I also noticed that you have two colors defined so there is an unknown one `???` left for you to fill in.
        scale_y_continuous(limits = extrema, expand = c(0, 0)) + # If you want to remove the white space left for axes limits, you should set expand = c(0, 0). It is almost certainly not recommended to set any margins to negative values.
        labs(x = "Time Post-Infestation (tpi)", y = "Mean FPKM", title = title) + 
        guides(y = guide_prism_minor()) +
        theme_bw() + 
        theme(
          plot.title = element_text(face = "bold.italic", size = 16, family = "sans", hjust = .5),
          axis.title = element_text(size = 14), 
          axis.text = element_text(size = 12), 
          axis.ticks.y = element_line(color = "black"), 
          panel.grid = element_blank(), 
          panel.border = element_rect(colour = "black", fill = NA), 
          plot.margin = unit(c(0,0.5,0.25,0.5), "cm"), 
          legend.position = "none"
        )
    }
    
    tor.responsive$FPKM.Mean <- rowMeans(tor.responsive[5:7])
    extrema <- range(tor.responsive$FPKM.Mean)
    result <-
      tor.responsive %>% 
      mutate(Genotype = factor(Genotype, c("S", "???"))) %>% # Don't forget to change this `???` too.
      nest(data = -Gene.Name) %>% 
      mutate(plots = mapply(
        plotf, data, Gene.Name, 
        MoreArgs = list(extrema = extrema), SIMPLIFY = FALSE
      ))
    

    Output

    > result
    # A tibble: 11 x 3
       Gene.Name data             plots 
       <chr>     <list>           <list>
     1 MsLHCB1.1 <tibble [1 x 7]> <gg>  
     2 MsLHCA6   <tibble [1 x 7]> <gg>  
     3 MsPLGG1-A <tibble [1 x 7]> <gg>  
     4 MsRPI3-B  <tibble [1 x 7]> <gg>  
     5 MsRPI1-B  <tibble [1 x 7]> <gg>  
     6 MsPGK1    <tibble [1 x 7]> <gg>  
     7 MsCFBP1-A <tibble [1 x 7]> <gg>  
     8 MsPSBTN   <tibble [1 x 7]> <gg>  
     9 MsTKL-1   <tibble [1 x 7]> <gg>  
    10 MsRCA-A   <tibble [1 x 7]> <gg>  
    11 MsCRD1-B  <tibble [1 x 7]> <gg>  
    

    You can then access, for instance, plot 7 by typing result$plots[[7L]] in your R console. The plot should look like this