2

Overview:

I have produced a series of maps (see below) using the R-code below, and I used plot_grid() in the Cowplot package to arrange the plots using the two data frames below called "QuercusRobur 1" and "QuercusRobur2".

Problem:

The plots look really good; however, the text labels are not well aligned. A few labels overlay the top of y-axis called Latitude, and two of the text labels called "A: Urbanisation Index" and "B: Urbanisation Index" are not positioned above their plots, and they also overlay the main titles called "Observation Period 1" and "Observation Period 2".

Does anyone know how to neatly align the plot labels so they are positioned in the top lefthand corner of each plot but also prevent them from overlaying the y-axis or parts of the map (see desired output below)?

If anyone can help, I would be deeply appreciative

R-Code

##Import Packages
    library(ggplot2)
    library(maps)
    library(mapdata)
    library(tidyverse)

 ##Get a map of the UK from maps:
        UK <- map_data(map = "world", region = "UK")
        head(UK)
        dim(UK)

        ##Produce point data

        MapUK<-ggplot(data = UK, aes(x = long, y = lat, group = group)) + 
                   geom_polygon() +
                   coord_map()

        ##head
        head(QuercusRobur1)
        head(QuercusRobur2)

        ##Remove weird data points
        QuercusRobur1<-QuercusRobur1%>%filter(Longitude<=3)

        ##Observation 1

        p1 <- ggplot(QuercusRobur1,
                    aes(x = Longitude, y = Latitude)) +
          geom_polygon(data = UK,
                       aes(x = long, y = lat, group = group), 
                       inherit.aes = FALSE) +
          geom_point() +
          coord_map(xlim = c(-10, 5)) + #limits added as there are some points really far away
          theme_classic()

   Urban1<-p1 + 
          aes(color = Urbanisation_index) + 
          scale_color_discrete(name = "Urbanisation Index",
                               labels = c("Urban", "Suburban", "Village", "Rural"))

   Stand1<-p1 + 
          aes(color = Stand_density_index) + 
          scale_color_discrete(name = "Stand Density Index",
                               labels = c("Standing alone",
                                          "Within a few trees or close proximity to other trees", 
                                          "Within a stand of 10-30 trees",
                                          "Large or woodland"))

 Phenology1<-p1 + 
          aes(color = factor(Phenological_Index)) +
          scale_color_discrete(name = "Phenological Index",
                               labels = c("No indication of autumn timing", 
                                          "First autumn tinting", 
                                          "Partial autumn tinting (>25% of leaves)", 
                                          "Advanced autumn tinting (>75% of leaves)"))

 ##Observation 2

 p2 <- ggplot(QuercusRobur2,
             aes(x = Longitude, y = Latitude)) +
   geom_polygon(data = UK,
                aes(x = long, y = lat, group = group), 
                inherit.aes = FALSE) +
   geom_point() +
   coord_map(xlim = c(-10, 5)) + #limits added as there are some points really far away
   theme_classic()

 Urban2<-p2 + 
   aes(color = Urbanisation_index) + 
   scale_color_discrete(name = "Urbanisation Index",
                        labels = c("Urban", "Suburban", "Village", "Rural"))

 Stand2<-p2 + 
   aes(color = Stand_density_.index) + 
   scale_color_discrete(name = "Stand Density Index",
                        labels = c("Standing alone",
                                   "Within a few trees or close proximity to other trees", 
                                   "Within a stand of 10-30 trees",
                                   "Large or woodland"))

 Phenology2<-p2 + 
   aes(color = factor(Phenological_Index)) +
   scale_color_discrete(name = "Phenological Index",
                        labels = c("No indication of autumn timing", 
                                   "First autumn tinting", 
                                   "Partial autumn tinting (>25% of leaves)", 
                                   "Advanced autumn tinting (>75% of leaves)"))

##Arrange the individual plots into one main plot



plot_grid(Urban1 + ggtitle("Observational Period 1"), 
       Urban2 + ggtitle("Observational Period 2"), 
       Stand1,
       Stand2,
       Phenology1,
       Phenology2, 
       labels=c("A: Urbanisation Index", "B: Urbanisation Index",
                "C: Stand Density Index","D: Stand Density Index",
                "E: Phenological Index","F: Phenological Index"),
       align = "v", 

       label_fontface="bold",
       label_fontfamily="Times New Roman",
       label_size = 8,
       rel_widths = c(1, 1.3),
       ncol = 2,
       nrow = 3,
       hjust = 0, 
       label_x = 0.01)

Plot produced from R-code

enter image description here

Desired Output

enter image description here

Data frame - QuercusRobur1

structure(list(Obs_.no = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 19L, 
20L, 21L, 22L, 23L, 24L, 25L, 28L, 29L, 30L, 31L, 32L, 33L, 34L, 
35L, 36L, 37L, 38L, 39L, 44L, 45L, 46L, 47L, 57L, 58L, 59L, 60L, 
61L, 62L, 63L, 64L, 65L, 66L, 67L, 68L, 69L, 70L, 71L, 72L, 74L, 
75L, 81L, 82L, 83L, 84L, 85L, 86L, 87L, 88L, 89L, 90L, 91L, 93L, 
102L, 103L, 104L, 112L, 113L, 114L, 115L, 116L, 117L, 118L, 119L, 
120L, 121L, 122L, 123L, 124L, 125L, 126L, 127L, 128L, 129L, 130L, 
131L, 135L, 136L, 137L, 138L, 143L, 144L, 145L, 146L, 147L, 148L, 
149L, 150L, 151L, 152L, 153L, 154L, 155L, 158L, 159L, 160L, 161L, 
162L, 163L, 164L, 165L, 169L, 170L, 171L, 172L, 177L, 178L, 179L, 
180L, 181L, 182L, 183L, 184L, 185L, 186L, 187L, 188L, 189L, 190L, 
191L, 192L, 193L, 194L, 195L, 196L, 200L), Date_observed = structure(c(4L, 
15L, 6L, 6L, 6L, 6L, 2L, 2L, 8L, 8L, 8L, 8L, 8L, 8L, 6L, 6L, 
6L, 6L, 6L, 6L, 11L, 11L, 11L, 11L, 12L, 7L, 7L, 9L, 9L, 9L, 
9L, 5L, 5L, 5L, 5L, 14L, 14L, 14L, 14L, 3L, 3L, 3L, 3L, 3L, 3L, 
3L, 3L, 6L, 6L, 5L, 5L, 9L, 9L, 9L, 9L, 3L, 3L, 3L, 3L, 4L, 4L, 
1L, 1L, 11L, 6L, 6L, 6L, 6L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 
10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 3L, 3L, 3L, 3L, 11L, 
11L, 11L, 4L, 4L, 4L, 4L, 8L, 8L, 10L, 10L, 10L, 10L, 9L, 9L, 
9L, 9L, 3L, 3L, 3L, 3L, 9L, 9L, 9L, 9L, 2L, 2L, 2L, 2L, 13L, 
13L, 13L, 13L, 8L, 8L, 8L, 8L, 10L, 10L, 10L, 10L, 3L, 3L, 3L, 
3L, 13L), .Label = c("10/1/18", "10/19/18", "10/20/18", "10/21/18", 
"10/22/18", "10/23/18", "10/24/18", "10/25/18", "10/26/18", "10/27/18", 
"10/28/18", "10/28/19", "10/29/18", "12/9/18", "8/20/18"), class = "factor"), 
    Latitude = c(51.4175, 52.12087, 52.0269, 52.0269, 52.0269, 
    52.0269, 52.947709, 52.947709, 51.491811, 51.491811, 52.59925, 
    52.59925, 52.59925, 52.59925, 51.60157, 51.60157, 52.6888, 
    52.6888, 52.6888, 52.6888, 50.697802, 50.697802, 50.697802, 
    50.697802, 53.62417, 50.446841, 50.446841, 53.959679, 53.959679, 
    53.959679, 53.959679, 51.78375, 51.78375, 51.78375, 51.78375, 
    51.456965, 51.456965, 51.456965, 51.456965, 51.3651, 51.3651, 
    51.3651, 51.3651, 52.01182, 52.01182, 52.01182, 52.01182, 
    50.114277, 50.114277, 51.43474, 51.43474, 51.10676, 51.10676, 
    51.10676, 51.10676, 50.435984, 50.435984, 50.435984, 50.435984, 
    51.78666, 51.78666, 52.441088, 52.441088, 52.552344, 49.259471, 
    49.259471, 49.259471, 49.259471, 50.461625, 50.461625, 50.461625, 
    50.461625, 51.746642, 51.746642, 51.746642, 51.746642, 52.2501, 
    52.2501, 52.2501, 52.2501, 52.423336, 52.423336, 52.423336, 
    52.423336, 53.615575, 53.615575, 53.615575, 53.615575, 51.08474, 
    51.08474, 51.08474, 53.19329, 53.19329, 53.19329, 53.19329, 
    55.96785, 55.96785, 56.52664, 56.52664, 56.52664, 56.52664, 
    51.8113, 51.8113, 51.8113, 51.8113, 52.580157, 52.580157, 
    52.580157, 52.580157, 50.52008, 50.52008, 50.52008, 50.52008, 
    51.48417, 51.48417, 51.48417, 51.48417, 54.58243, 54.58243, 
    54.58243, 54.58243, 52.58839, 52.58839, 52.58839, 52.58839, 
    52.717283, 52.717283, 52.717283, 52.717283, 50.740764, 50.740764, 
    50.740764, 50.740764, 52.57937), Longitude = c(-0.32118, 
    -0.29293, -0.7078, -0.7078, -0.7078, -0.7078, -1.435407, 
    -1.435407, -3.210324, -3.210324, 1.33011, 1.33011, 1.33011, 
    1.33011, -3.67111, -3.67111, -3.30909, -3.30909, -3.30909, 
    -3.30909, -2.11692, -2.11692, -2.11692, -2.11692, -2.43155, 
    -3.706923, -3.706923, -1.061008, -1.061008, -1.061008, -1.061008, 
    -0.65046, -0.65046, -0.65046, -0.65046, -2.624917, -2.624917, 
    -2.624917, -2.624917, 0.70706, 0.70706, 0.70706, 0.70706, 
    -0.70082, -0.70082, -0.70082, -0.70082, -5.541128, -5.541128, 
    0.45981, 0.45981, -2.32071, -2.32071, -2.32071, -2.32071, 
    -4.105617, -4.105617, -4.105617, -4.105617, -0.71433, -0.71433, 
    -0.176158, -0.176158, -1.337177, -123.107788, -123.107788, 
    -123.107788, -123.107788, 3.560973, 3.560973, 3.560973, 3.560973, 
    0.486416, 0.486416, 0.486416, 0.486416, -0.8825, -0.8825, 
    -0.8825, -0.8825, -1.787563, -1.787563, -1.787563, -1.787563, 
    -2.432959, -2.432959, -2.432959, -2.432959, -0.73645, -0.73645, 
    -0.73645, -0.63793, -0.63793, -0.63793, -0.63793, -3.18084, 
    -3.18084, -3.40313, -3.40313, -3.40313, -3.40313, -0.22894, 
    -0.22894, -0.22894, -0.22894, -1.948571, -1.948571, -1.948571, 
    -1.948571, -4.20756, -4.20756, -4.20756, -4.20756, -0.34854, 
    -0.34854, -0.34854, -0.34854, -5.93229, -5.93229, -5.93229, 
    -5.93229, -1.96843, -1.96843, -1.96843, -1.96843, -2.410575, 
    -2.410575, -2.410575, -2.410575, -2.361234, -2.361234, -2.361234, 
    -2.361234, -1.89325), Altitude = c(5L, 0L, 68L, 68L, 68L, 
    68L, 104L, 104L, 15L, 15L, 23L, 23L, 23L, 23L, 184L, 184L, 
    176L, 176L, 176L, 176L, 12L, 12L, 12L, 12L, 178L, 36L, 36L, 
    11L, 11L, 11L, 11L, 210L, 210L, 210L, 210L, 97L, 97L, 97L, 
    97L, 23L, 23L, 23L, 23L, 0L, 0L, 0L, 0L, 9L, 9L, 4L, 4L, 
    200L, 200L, 200L, 200L, 160L, 160L, 160L, 160L, 166L, 166L, 
    0L, 0L, 0L, 47L, 47L, 47L, 47L, 58L, 58L, 58L, 58L, 43L, 
    43L, 43L, 43L, 97L, 97L, 97L, 97L, 133L, 133L, 133L, 133L, 
    123L, 123L, 123L, 123L, 128L, 128L, 128L, 15L, 15L, 15L, 
    15L, 14L, 14L, 65L, 65L, 65L, 65L, 129L, 129L, 129L, 129L, 
    140L, 140L, 140L, 140L, 18L, 18L, 18L, 18L, 30L, 30L, 30L, 
    30L, 19L, 19L, 19L, 19L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    96L, 96L, 96L, 96L, 169L), Species = structure(c(1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "Quercus robur", class = "factor"), 
    Tree_diameter = c(68.8, 10, 98.5, 97, 32.5, 45.1, 847, 817, 
    62, 71, 140, 111.4, 114.6, 167.1, 29, 40.1, 68, 45, 60, 54, 
    104, 122, 85, 71, 81, 39.8, 43.6, 20.1, 17.8, 15.6, 12.1, 
    81.8, 102.5, 75.5, 57.3, 0.3, 0.2, 0.3, 0.3, 70, 36, 53, 
    44, 31.5, 27.1, 23.3, 22, 69.4, 37.3, 19.9, 14.6, 196, 122, 
    118, 180, 58.6, 54.1, 58, 61.5, 58.4, 61, 134, 64, 52.2, 
    170, 114, 127, 158, 147.4, 135.3, 122.9, 104.1, 263, 237, 
    322, 302, 175, 182, 141, 155, 89, 41, 70, 83, 141, 86.5, 
    82, 114.5, 129, 127, 143, 125, 92, 68, 90, 24.5, 20.1, 63.7, 
    39.8, 66.2, 112.4, 124.5, 94.1, 68.6, 74.4, 23.6, 27.7, 22.9, 
    25.2, 24.2, 54.7, 43, 33.1, 306, 274, 56, 60, 72.5, 128.5, 
    22, 16, 143, 103, 53, 130, 48.4, 69.8, 6.4, 18.6, 129.2, 
    41.7, 57.6, 14, 41.7), Urbanisation_index = c(2L, 1L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
    4L, 4L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 2L, 2L, 2L, 2L, 4L, 4L, 
    4L, 4L, 2L, 2L, 2L, 2L, 4L, 4L, 4L, 4L, 2L, 2L, 2L, 2L, 4L, 
    4L, 4L, 4L, 4L, 4L, 4L, 4L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 
    4L, 2L, 2L, 2L, 2L, 4L, 4L, 4L, 4L, 3L, 3L, 3L, 3L, 2L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 
    4L, 4L, 1L, 1L, 4L, 4L, 4L, 4L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
    3L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 2L, 2L, 2L, 2L, 4L, 4L, 4L, 4L, 2L), Stand_density_index = c(3L, 
    1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    4L, 4L, 4L, 4L, 2L, 2L, 2L, 2L, 4L, 1L, 1L, 4L, 4L, 4L, 4L, 
    4L, 4L, 4L, 4L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 
    3L, 3L, 3L, 3L, 3L, 2L, 2L, 4L, 4L, 3L, 3L, 3L, 3L, 4L, 3L, 
    4L, 4L, 3L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    2L, 2L, 2L, 2L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 3L, 3L, 3L, 
    2L, 2L, 2L, 2L, 2L, 3L, 4L, 4L, 4L, 4L, 2L, 2L, 2L, 2L, 2L, 
    2L, 2L, 1L, 4L, 4L, 4L, 4L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 
    2L, 2L, 2L, 2L, 3L, 3L, 3L, 2L, 4L, 4L, 4L, 4L, 4L), Canopy_Index = c(85L, 
    85L, 85L, 75L, 45L, 25L, 75L, 65L, 75L, 75L, 95L, 95L, 95L, 
    95L, 95L, 65L, 85L, 65L, 95L, 85L, 85L, 85L, 75L, 75L, 65L, 
    85L, 85L, 75L, 75L, 85L, 65L, 95L, 85L, 95L, 95L, 75L, 75L, 
    85L, 85L, 85L, 85L, 85L, 75L, 85L, 85L, 85L, 85L, 75L, 75L, 
    85L, 85L, 65L, 75L, 85L, 75L, 95L, 95L, 95L, 95L, 75L, 65L, 
    95L, 95L, 55L, 75L, 65L, 75L, 65L, 85L, 95L, 95L, 75L, 95L, 
    75L, 95L, 65L, 75L, 75L, 85L, 85L, 65L, 95L, 65L, 65L, 65L, 
    65L, 65L, 65L, 85L, 85L, 75L, 95L, 85L, 85L, 75L, 45L, 55L, 
    35L, 35L, 25L, 25L, 95L, 85L, 75L, 85L, 85L, 75L, 75L, 65L, 
    75L, 85L, 65L, 45L, 95L, 95L, 95L, 95L, 65L, 75L, 45L, 35L, 
    75L, 95L, 95L, 85L, 75L, 65L, 85L, 95L, 75L, 85L, 85L, 95L, 
    65L), Phenological_Index = c(2L, 4L, 2L, 2L, 4L, 4L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 2L, 3L, 2L, 2L, 2L, 2L, 
    2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 2L, 1L, 1L, 2L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 2L, 2L, 2L, 3L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 4L, 4L, 1L, 2L, 2L, 2L, 
    2L, 2L, 2L, 2L, 3L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 
    3L, 4L, 4L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
    4L, 1L, 1L, 1L, 1L, 3L, 2L, 3L, 3L, 3L, 3L, 4L, 3L, 2L, 3L, 
    2L, 2L, 2L, 1L, 3L, 1L, 4L)), class = "data.frame", row.names = c(NA, 
-134L))

Data frame - QuercusRobur2

   structure(list(X = c(1L, 2L, 3L, 4L, 13L, 14L, 15L, 18L, 19L, 
20L, 21L, 22L, 23L, 24L, 25L, 26L, 27L, 28L, 29L, 30L, 35L, 36L, 
37L, 38L, 48L, 49L, 50L, 51L, 52L, 53L, 54L, 55L, 56L, 57L, 58L, 
59L, 63L, 64L, 68L, 69L, 70L, 71L, 72L, 73L, 74L, 75L, 76L, 77L, 
78L, 80L, 89L, 90L, 91L, 95L, 96L, 97L, 98L, 99L, 100L, 101L, 
102L, 103L, 104L, 105L, 106L, 107L, 108L, 109L, 110L, 111L, 112L, 
113L, 114L, 118L, 119L, 120L, 121L, 126L, 127L, 128L, 129L, 130L, 
131L, 132L, 133L, 134L, 135L, 136L, 137L, 138L, 141L, 142L, 143L, 
144L, 148L, 149L, 150L, 151L, 156L, 157L, 158L, 159L, 160L, 161L, 
162L, 163L, 164L, 165L, 166L, 167L, 168L, 169L, 170L, 171L, 172L, 
173L, 174L, 175L, 179L, 180L, 181L, 182L, 183L, 185L, 187L, 189L, 
190L, 191L, 192L, 193L, 194L, 195L, 196L, 208L, 209L, 210L, 212L, 
214L, 225L, 226L, 227L, 228L, 229L, 230L, 231L, 242L, 243L, 244L, 
245L, 246L, 247L, 248L, 249L, 250L, 251L, 252L, 253L, 254L, 255L, 
256L, 257L, 258L, 259L, 260L, 261L), Obs_no = c(1L, 2L, 3L, 4L, 
13L, 14L, 15L, 18L, 19L, 20L, 21L, 22L, 23L, 24L, 25L, 26L, 27L, 
28L, 29L, 30L, 35L, 36L, 37L, 38L, 48L, 49L, 50L, 51L, 52L, 53L, 
54L, 55L, 56L, 57L, 58L, 59L, 63L, 64L, 68L, 69L, 70L, 71L, 72L, 
73L, 74L, 75L, 76L, 77L, 78L, 80L, 89L, 90L, 91L, 95L, 96L, 97L, 
98L, 99L, 100L, 101L, 102L, 103L, 104L, 105L, 106L, 107L, 108L, 
109L, 110L, 111L, 112L, 113L, 114L, 118L, 119L, 120L, 121L, 126L, 
127L, 128L, 129L, 130L, 131L, 132L, 133L, 134L, 135L, 136L, 137L, 
138L, 141L, 142L, 143L, 144L, 148L, 149L, 150L, 151L, 156L, 157L, 
158L, 159L, 160L, 161L, 162L, 163L, 164L, 165L, 166L, 167L, 168L, 
169L, 170L, 171L, 172L, 173L, 174L, 175L, 179L, 180L, 181L, 182L, 
183L, 185L, 187L, 189L, 190L, 191L, 192L, 193L, 194L, 195L, 196L, 
208L, 209L, 210L, 212L, 214L, 225L, 226L, 227L, 228L, 229L, 230L, 
231L, 242L, 243L, 244L, 245L, 246L, 247L, 248L, 249L, 250L, 251L, 
252L, 253L, 254L, 255L, 256L, 257L, 258L, 259L, 260L, 261L), 
    Date_observed = structure(c(9L, 14L, 3L, 3L, 12L, 12L, 10L, 
    10L, 8L, 8L, 8L, 8L, 11L, 11L, 11L, 11L, 5L, 5L, 9L, 9L, 
    13L, 13L, 13L, 13L, 8L, 8L, 8L, 8L, 13L, 13L, 13L, 13L, 7L, 
    7L, 7L, 7L, 6L, 6L, 11L, 11L, 11L, 11L, 11L, 11L, 4L, 4L, 
    4L, 4L, 12L, 12L, 12L, 12L, 5L, 1L, 1L, 1L, 1L, 5L, 5L, 5L, 
    5L, 12L, 12L, 12L, 12L, 11L, 11L, 11L, 11L, 2L, 2L, 2L, 2L, 
    3L, 3L, 3L, 3L, 13L, 13L, 13L, 8L, 8L, 8L, 8L, 13L, 13L, 
    12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 13L, 13L, 13L, 13L, 
    3L, 3L, 3L, 3L, 13L, 13L, 13L, 13L, 10L, 10L, 10L, 10L, 12L, 
    12L, 12L, 12L, 3L, 3L, 3L, 3L, 13L, 13L, 5L, 5L, 5L, 11L, 
    11L, 12L, 12L, 12L, 12L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 
    9L, 9L, 12L, 12L, 12L, 12L, 8L, 8L, 8L, 5L, 5L, 5L, 5L, 12L, 
    12L, 12L, 12L, 11L, 11L, 11L, 11L, 13L, 13L, 13L, 13L, 5L, 
    5L, 5L, 5L), .Label = c("10/23/18", "11/18/18", "11/30/18", 
    "12/1/18", "12/10/18", "12/12/18", "12/2/18", "12/3/18", 
    "12/4/18", "12/6/18", "12/7/18", "12/8/18", "12/9/18", "9/10/18"
    ), class = "factor"), Latitude = c(51.41752, 52.243806, 52.947709, 
    52.947709, 51.491811, 51.491811, 51.60157, 51.60157, 52.68959, 
    52.68959, 52.68959, 52.68959, 50.697802, 50.697802, 50.697802, 
    50.697802, 53.62417, 53.62417, 50.446841, 50.446841, 53.959679, 
    53.959679, 53.959679, 53.959679, 51.78375, 51.78375, 51.78375, 
    51.78375, 51.456965, 51.456965, 51.456965, 51.456965, 52.011812, 
    52.011812, 52.011812, 52.011812, 50.121978, 50.121978, 51.43474, 
    51.43474, 51.10708, 51.10708, 51.10708, 51.10708, 50.435984, 
    50.435984, 50.435984, 50.435984, 51.78666, 51.78666, 52.441088, 
    52.441088, 52.552344, 49.259471, 49.259471, 49.259471, 49.259471, 
    50.462, 50.462, 50.462, 50.462, 51.746642, 51.746642, 51.746642, 
    51.746642, 52.2501, 52.2501, 52.2501, 52.2501, 52.42646, 
    52.42646, 52.42646, 52.42646, 53.615575, 53.615575, 53.615575, 
    53.615575, 51.08478, 51.08478, 51.08478, 53.19329, 53.19329, 
    53.19329, 53.19329, 55.968437, 55.968437, 56.52664, 56.52664, 
    56.52664, 56.52664, 51.8113, 51.8113, 51.8113, 51.8113, 50.52008, 
    50.52008, 50.52008, 50.52008, 51.48417, 51.48417, 51.48417, 
    51.48417, 54.58243, 54.58243, 54.58243, 54.58243, 52.58839, 
    52.58839, 52.58839, 52.58839, 52.717283, 52.717283, 52.717283, 
    52.717283, 50.740764, 50.740764, 50.740764, 50.740764, 50.733412, 
    50.733412, 50.79926, 50.79926, 50.79926, 53.675788, 53.675788, 
    48.35079, 48.35079, 48.35079, 48.35079, 51.36445, 51.36445, 
    51.36445, 51.36445, 52.122402, 52.122402, 52.122402, 52.16104, 
    52.16104, 51.88468, 51.88468, 51.88468, 51.88468, 52.34015, 
    52.34015, 52.34015, 52.026042, 52.026042, 52.026042, 52.026042, 
    51.319032, 51.319032, 51.319032, 51.319032, 51.51365, 51.51365, 
    51.51365, 51.51365, 53.43202, 53.43202, 53.43202, 53.43202, 
    51.50797, 51.50797, 51.50797, 51.50797), Longitude = c(-0.32116, 
    1.30786, -1.435407, -1.435407, -3.210324, -3.210324, -3.67111, 
    -3.67111, -3.3081, -3.3081, -3.3081, -3.3081, -2.11692, -2.11692, 
    -2.11692, -2.11692, -2.43155, -2.43155, -3.706923, -3.706923, 
    -1.061008, -1.061008, -1.061008, -1.061008, -0.65046, -0.65046, 
    -0.65046, -0.65046, -2.624917, -2.624917, -2.624917, -2.624917, 
    -0.70082, -0.70082, -0.70082, -0.70082, -5.555169, -5.555169, 
    0.45981, 0.45981, -2.32027, -2.32027, -2.32027, -2.32027, 
    -4.105617, -4.105617, -4.105617, -4.105617, -0.71433, -0.71433, 
    -0.176158, -0.176158, -1.337177, -123.107788, -123.107788, 
    -123.107788, -123.107788, -3.5607, -3.5607, -3.5607, -3.5607, 
    0.486416, 0.486416, 0.486416, 0.486416, -0.8825, -0.8825, 
    -0.8825, -0.8825, -1.78771, -1.78771, -1.78771, -1.78771, 
    -2.432959, -2.432959, -2.432959, -2.432959, -0.73626, -0.73626, 
    -0.73626, -0.63793, -0.63793, -0.63793, -0.63793, -3.179732, 
    -3.179732, -3.40313, -3.40313, -3.40313, -3.40313, -0.22894, 
    -0.22894, -0.22894, -0.22894, -4.20756, -4.20756, -4.20756, 
    -4.20756, -0.34854, -0.34854, -0.34854, -0.34854, -5.93229, 
    -5.93229, -5.93229, -5.93229, -1.96843, -1.96843, -1.96843, 
    -1.96843, -2.410575, -2.410575, -2.410575, -2.410575, -2.361234, 
    -2.361234, -2.361234, -2.361234, -2.014029, -2.014029, -3.19446, 
    -3.19446, -3.19446, -1.272404, -1.272404, 10.91812, 10.91812, 
    10.91812, 10.91812, -0.23106, -0.23106, -0.23106, -0.23106, 
    -0.487443, -0.487443, -0.487443, 0.18702, 0.18702, -0.17853, 
    -0.17853, -0.17853, -0.17853, -1.27795, -1.27795, -1.27795, 
    -0.503113, -0.503113, -0.503113, -0.503113, -0.472994, -0.472994, 
    -0.472994, -0.472994, -3.18722, -3.18722, -3.18722, -3.18722, 
    -2.27968, -2.27968, -2.27968, -2.27968, -0.25931, -0.25931, 
    -0.25931, -0.25931), Altitude = c(0, 0, 103.9, 103.9, 15, 
    15, 184, 184, 176, 176, 176, 176, 12, 12, 12, 12, 178, 178, 
    36, 36, 11, 11, 11, 11, 210, 210, 210, 210, 97, 97, 97, 97, 
    0, 0, 0, 0, 68, 68, 4, 4, 200, 200, 200, 200, 160, 160, 160, 
    160, 165.8, 165.8, 0, 0, 0, 47, 47, 47, 47, 0, 0, 0, 0, 43, 
    43, 43, 43, 97, 97, 97, 97, 133, 133, 133, 133, 123, 123, 
    123, 123, 127, 127, 127, 15, 15, 15, 15, 14, 14, 65, 65, 
    65, 65, 129, 129, 129, 129, 18, 18, 18, 18, 30, 30, 30, 30, 
    19, 19, 19, 19, 0, 0, 0, 0, 0, 0, 0, 0, 96, 96, 96, 96, 0, 
    0, 0, 0, 0, 49, 49, 0, 0, 0, 0, 48, 48, 48, 48, 43, 43, 43, 
    75, 75, 94, 94, 94, 94, 112, 112, 112, 103, 103, 103, 103, 
    0, 0, 0, 0, 37.5, 37.5, 37.5, 37.5, 29, 29, 29, 29, 63, 63, 
    63, 63), Species = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "Quercus robur", class = "factor"), 
    Tree_diameter = c(68.8, 300, 847, 817, 62, 71, 29, 40.1, 
    68, 45, 60, 54, 104, 122, 85, 71, 81, 118, 39.8, 43.6, 19.8, 
    16.6, 15.1, 11.9, 81.8, 102.5, 75.5, 57.3, 0.3, 0.2, 0.3, 
    0.3, 99, 85, 74, 68, 82, 51.8, 19.9, 14.6, 196, 122, 118, 
    180, 58.6, 54.1, 58, 61.5, 58.4, 61, 134, 64, 52.2, 170, 
    114, 127, 158, 147.4, 135.3, 122.9, 104.1, 263, 237, 322, 
    302, 173, 186, 144, 155, 89, 41, 68, 83, 141.6, 85.5, 82.8, 
    114.1, 129, 127, 143, 125, 92, 68, 90, 25, 20, 63.7, 39.8, 
    66.2, 112.4, 124.5, 94.1, 68.6, 74.4, 24.2, 54.7, 43, 33.1, 
    306, 274, 56, 60, 72.5, 128.5, 22, 16, 143, 103, 53, 130, 
    48.4, 69.8, 6.4, 18.6, 129.2, 41.7, 57.6, 14, 320, 352, 120.9, 
    108.3, 53.2, 274, 85, 52, 43, 38, 37, 219, 215, 216, 175, 
    85.9, 49.7, 97.1, 40.8, 62.4, 181.5, 149.7, 122, 143.6, 148, 
    145, 99, 27.5, 32, 54, 54.1, 169, 152, 160, 138, 90.8, 87.9, 
    77.4, 81.2, 91.7, 62.7, 50, 72.9, 24.8, 61, 88.6, 80.1), 
    Urbanisation_index = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 
    4L, 4L, 4L, 4L, 4L, 4L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 2L, 
    2L, 2L, 2L, 4L, 4L, 4L, 4L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    4L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 
    4L, 4L, 2L, 2L, 2L, 2L, 4L, 4L, 4L, 4L, 3L, 3L, 3L, 3L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 
    4L, 4L, 4L, 1L, 1L, 4L, 4L, 4L, 4L, 3L, 3L, 3L, 3L, 3L, 3L, 
    3L, 3L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 
    2L, 2L, 2L, 4L, 4L, 4L, 4L, 4L, 4L, 2L, 2L, 2L, 3L, 4L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 4L, 4L, 1L, 1L, 1L, 
    1L, 4L, 4L, 4L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 2L, 2L, 2L, 
    2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L), .Label = c("1", "2", 
    "3", "4"), class = "factor"), Stand_density_.index = structure(c(3L, 
    4L, 2L, 2L, 2L, 2L, 2L, 2L, 4L, 4L, 4L, 4L, 2L, 2L, 2L, 2L, 
    4L, 4L, 1L, 1L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 2L, 2L, 2L, 
    2L, 3L, 3L, 3L, 3L, 3L, 2L, 3L, 3L, 2L, 2L, 4L, 4L, 3L, 3L, 
    3L, 3L, 4L, 3L, 4L, 4L, 3L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
    4L, 3L, 3L, 3L, 2L, 2L, 2L, 2L, 2L, 3L, 4L, 4L, 4L, 4L, 2L, 
    2L, 2L, 2L, 4L, 4L, 4L, 4L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 
    2L, 2L, 2L, 2L, 3L, 3L, 3L, 2L, 4L, 4L, 4L, 4L, 4L, 4L, 2L, 
    2L, 2L, 2L, 4L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
    4L, 4L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 4L, 4L, 4L, 4L, 3L, 3L, 
    3L, 3L, 4L, 4L, 4L, 2L, 3L, 3L, 3L, 3L, 2L, 2L, 2L, 2L), .Label = c("1", 
    "2", "3", "4"), class = "factor"), Canopy_Index = c(15L, 
    95L, 45L, 5L, 5L, 5L, 25L, 15L, 25L, 25L, 35L, 35L, 25L, 
    35L, 15L, 15L, 15L, 15L, 5L, 5L, 5L, 5L, 5L, 5L, 35L, 35L, 
    55L, 35L, 5L, 5L, 5L, 5L, 95L, 95L, 95L, 95L, 25L, 25L, 15L, 
    5L, 25L, 25L, 25L, 25L, 5L, 5L, 5L, 5L, 5L, 5L, 35L, 25L, 
    5L, 35L, 35L, 25L, 25L, 5L, 5L, 5L, 5L, 35L, 25L, 25L, 25L, 
    5L, 5L, 15L, 15L, 35L, 65L, 35L, 35L, 25L, 25L, 25L, 25L, 
    15L, 15L, 5L, 35L, 35L, 45L, 35L, 5L, 15L, 15L, 25L, 5L, 
    15L, 15L, 5L, 5L, 15L, 5L, 5L, 5L, 5L, 5L, 85L, 5L, 35L, 
    15L, 5L, 5L, 5L, 25L, 25L, 15L, 35L, 95L, 95L, 95L, 95L, 
    15L, 15L, 5L, 25L, 25L, 5L, 15L, 15L, 5L, 15L, 5L, 25L, 25L, 
    25L, 25L, 5L, 5L, 5L, 5L, 25L, 25L, 55L, 35L, 25L, 15L, 15L, 
    25L, 15L, 45L, 35L, 35L, 15L, 35L, 15L, 15L, 35L, 15L, 25L, 
    25L, 15L, 15L, 15L, 15L, 5L, 5L, 5L, 5L, 5L, 5L, 15L, 15L
    ), Phenological_Index = c(4L, 4L, 3L, 4L, 2L, 4L, 4L, 4L, 
    4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
    4L, 4L, 4L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
    4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 3L, 
    4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
    4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
    4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
    4L, 4L, 4L, 4L, 3L, 2L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
    4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
    4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
    4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
    4L, 4L, 4L, 4L, 4L, 4L, 4L)), row.names = c(NA, -165L), class = "data.frame")  
Alice Hobbs
  • 1,021
  • 1
  • 15
  • 31

1 Answers1

3

How about using subtitle for labeling each individual plot?

## Observation 1
p1 <- ggplot(
  QuercusRobur1,
  aes(x = Longitude, y = Latitude)
) +
  geom_polygon(
    data = UK,
    aes(x = long, y = lat, group = group),
    inherit.aes = FALSE
  ) +
  coord_map(xlim = c(-10, 5)) + # limits added as there are some points really far away
  theme_classic()


Urban1 <- p1 +
  geom_point(aes(color = factor(Urbanisation_index))) +
  scale_color_discrete(
    name = "Urbanisation Index",
    labels = c("Urban", "Suburban", "Village", "Rural")
  ) +
  labs(subtitle = "A: Urbanisation Index") +
  theme(legend.justification = "left")

Stand1 <- p1 +
  geom_point(aes(color = factor(Stand_density_index))) +
  scale_color_discrete(
    name = "Stand Density Index",
    labels = c(
      "Standing alone",
      "Within a few trees or close proximity to other trees",
      "Within a stand of 10-30 trees",
      "Large or woodland"
    )
  ) +
  labs(subtitle = "C: Stand Density Index") +
  theme(legend.justification = "left")

## Observation 2
p2 <- ggplot(
  QuercusRobur2,
  aes(x = Longitude, y = Latitude)
) +
  geom_polygon(
    data = UK,
    aes(x = long, y = lat, group = group),
    inherit.aes = FALSE
  ) +
  coord_map(xlim = c(-10, 5)) + 
  theme_classic()

Urban2 <- p2 +
  geom_point(aes(color = factor(Urbanisation_index))) +
  scale_color_discrete(
    name = "Urbanisation Index",
    labels = c("Urban", "Suburban", "Village", "Rural")
  ) +
  labs(subtitle = "B: Urbanisation Index") +
  theme(legend.justification = "left")

Stand2 <- p2 +
  geom_point(aes(color = factor(Stand_density_.index))) +
  scale_color_discrete(
    name = "Stand Density Index",
    labels = c(
      "Standing alone",
      "Within a few trees or close proximity to other trees",
      "Within a stand of 10-30 trees",
      "Large or woodland"
    )
  ) +
  labs(subtitle = "D: Stand Density Index") +
  theme(legend.justification = "left")

## Arrange the individual plots into one main plot
plot_grid(
  Urban1 + ggtitle("Observational Period 1\n") + theme(plot.title = element_text(hjust = 1.0)),
  Urban2 + ggtitle("Observational Period 2\n") + theme(plot.title = element_text(hjust = 1.0)),
  Stand1,
  Stand2,
  align = "hv",
  axis = 'tblr',
  label_fontface = "bold",
  label_fontfamily = "Times New Roman",
  label_size = 8,
  rel_widths = c(1, 1.3),
  ncol = 2,
  nrow = 2,
  hjust = 0,
  label_x = 0.01
)

Edit: remove duplicate axis labels and legends then use egg::ggarrange to combine subplots.

## Observation 1
Urban1 <- p1 +
  geom_point(aes(color = factor(Urbanisation_index))) +
  scale_color_discrete(
    name = "Urbanisation Index",
    labels = c("Urban", "Suburban", "Village", "Rural")
  ) +
  labs(subtitle = "A: Urbanisation Index") +
  theme(legend.position = "none")

Stand1 <- p1 +
  geom_point(aes(color = factor(Stand_density_index))) +
  scale_color_discrete(
    name = "Stand Density Index",
    labels = c(
      "Standing alone",
      "Within a few trees or close proximity to other trees",
      "Within a stand of 10-30 trees",
      "Large or woodland"
    )
  ) +
  labs(subtitle = "C: Stand Density Index") +
  theme(legend.position = "none")

## Observation 2
p2 <- ggplot(
  QuercusRobur2,
  aes(x = Longitude, y = Latitude)
) +
  geom_polygon(
    data = UK,
    aes(x = long, y = lat, group = group),
    inherit.aes = FALSE
  ) +
  coord_map(xlim = c(-10, 5)) + 
  theme_classic() +
  ylab("")

Urban2 <- p2 +
  geom_point(aes(color = factor(Urbanisation_index))) +
  scale_color_discrete(
    name = "Urbanisation Index",
    labels = c("Urban", "Suburban", "Village", "Rural")
  ) +
  labs(subtitle = "B: Urbanisation Index") +
  theme(legend.justification = "left")

Stand2 <- p2 +
  geom_point(aes(color = factor(Stand_density_.index))) +
  scale_color_discrete(
    name = "Stand Density Index",
    labels = c(
      "Standing alone",
      "Within a few trees or close proximity to other trees",
      "Within a stand of 10-30 trees",
      "Large or woodland"
    )
  ) +
  labs(subtitle = "D: Stand Density Index") +
  theme(legend.justification = "left")

## Use the `egg` package
library(egg)
ggarrange(
  Urban1 + ggtitle("Observational Period 1\n") + theme(plot.title = element_text(hjust = 0.5)),
  Urban2 + ggtitle("Observational Period 2\n") + theme(plot.title = element_text(hjust = 0.5)),
  Stand1,
  Stand2,
  nrow = 2,
  ncol = 2
)

Tung
  • 26,371
  • 7
  • 91
  • 115
  • 1
    Hi Tung, this is amazing! This is exactly what I have been trying to achieve. I incorporated more code to incorporate the phenological index maps. After I plotted them, the points on the phenological index map (label F) did not plot, and the plots are now unaligned. Do you know how to fix this? Many thanks in advance if you can help. – Alice Hobbs Mar 10 '19 at 10:12
  • Glad that I could help! I only did 2x2 but it should work for any number of subplots. Have you tried playing around with `nrow`, `ncol`, `align = ` & `axis = ` arguments? See also this answer for more options https://stackoverflow.com/a/51220506/786542 – Tung Mar 10 '19 at 10:16
  • Ah! Great! I will give it a try. I think the problem is the nrow and ncol, but I don't understand why the point data did onto overlay on the map. I will try again – Alice Hobbs Mar 10 '19 at 10:24
  • 1
    Hi Tung. Thank you! It worked. You are a legend. Many thanks to you – Alice Hobbs Mar 10 '19 at 10:58
  • @AliceHobbs: btw you can make your plot a little bit better by removing all the legends on the left – Tung Mar 10 '19 at 11:32
  • See also these answers: https://stackoverflow.com/a/52067836/ & https://stackoverflow.com/a/49834950/ – Tung Mar 10 '19 at 11:41