Search code examples
rggplot2patchwork

R ggplot2 patchwork changes label location


Based on the sample and code below the label is positioned where intended when plotting individual ggplots, however, when I use patchwork to combine the plots, the location of the labels get's messed up.

How can I fix this so that the labels stay at the same location in all the plots via patchwork as in the ggplots?

Sample data (df):

structure(list(TMin = c(9.27700042724609, 9.36499977111816, 9.5310001373291, 
9.67700004577637, 9.69699954986572, 9.86499977111816, 9.95899963378906, 
10.0900001525879, 10.2849998474121, 10.4370002746582, 10.5170001983643, 
10.5790004730225, 10.6969995498657, 10.7930002212524, 10.9329996109009, 
11.0109996795654, 9.36400032043457, 9.4709997177124, 9.62600040435791, 
9.77600002288818, 9.95100021362305, 10.1199998855591, 10.2729997634888, 
10.3730001449585, 10.5500001907349, 10.668999671936, 10.7709999084473, 
10.8199996948242, 10.8920001983643, 10.9840002059937, 11.125, 
11.1909999847412, 11.2919998168945, 11.5319995880127, 11.7399997711182, 
11.9340000152588, 9.3730001449585, 9.58699989318848, 9.79800033569336, 
9.9980001449585, 10.2040004730225, 10.4370002746582, 10.5459995269775, 
10.6020002365112, 10.75, 10.875, 10.9630002975464, 11.0100002288818, 
11.039999961853, 11.1890001296997, 11.1909999847412, 11.2659997940063, 
11.3730001449585, 11.6090002059937, 11.831000328064, 9.58600044250488, 
9.80399990081787, 9.99699974060059, 10.2569999694824, 10.4630002975464, 
10.6219997406006, 10.710000038147, 10.7700004577637, 10.9350004196167, 
11.0570001602173, 11.0640001296997, 11.1709995269775, 11.2290000915527, 
11.1949996948242, 11.201000213623, 11.2709999084473, 11.4359998703003, 
11.6829996109009, 11.9020004272461, 9.81400012969971, 9.97900009155273, 
10.2399997711182, 10.4370002746582, 10.5939998626709, 10.7270002365112, 
10.7379999160767, 10.8269996643066, 10.9079999923706, 11.0120000839233, 
11.1160001754761, 11.2770004272461, 11.2639999389648, 11.25, 
11.1940002441406, 11.2629995346069, 11.4219999313354, 11.6750001907349, 
11.923999786377, 10.0500001907349, 10.2650003433228, 10.4449996948242, 
10.5970001220703, 10.6800003051758, 10.7729997634888, 10.9770002365112, 
11.0480003356934, 11.1099996566772, 11.2959995269775, 11.3409996032715, 
11.3070001602173, 11.2889995574951, 11.253999710083, 11.2749996185303, 
11.298999786377, 11.4280004501343, 11.6549997329712, 11.8920001983643, 
10.3070001602173, 10.4099998474121, 10.5930004119873, 10.8409996032715, 
10.9099998474121, 10.8760004043579, 11.1719999313354, 11.3299999237061, 
11.4320001602173, 11.5710000991821, 11.5649995803833, 11.414999961853, 
11.331000328064, 11.2829999923706, 11.3240003585815, 11.3990001678467, 
11.4940004348755, 11.6059999465942, 11.8030004501343, 10.4250001907349, 
10.6859998703003, 10.8909997940063, 11.0679998397827, 11.1680002212524, 
11.3929996490479, 11.6040000915527, 11.6759996414185, 11.7209997177124, 
11.6890001296997, 11.6169996261597, 11.5369997024536, 11.4729995727539, 
11.4809999465942, 11.5299997329712, 11.5790004730225, 11.706000328064, 
11.96399974823, 10.5249996185303, 10.7620000839233, 11.0609998703003, 
11.2270002365112, 11.3950004577637, 11.5880002975464, 11.6490001678467, 
11.7709999084473, 11.8439998626709, 11.8190002441406, 11.8179998397827, 
11.8240003585815, 11.7969999313354, 11.7729997634888, 11.7589998245239, 
11.8000001907349, 11.9910001754761, 12.3430004119873, 11.3909997940063, 
11.5719995498657, 11.6979999542236, 11.8590002059937, 11.9580001831055, 
11.9759998321533, 11.960000038147, 11.9610004425049, 12.0260000228882, 
11.5100002288818, 11.6529998779297, 11.9490003585815, 12.1890001296997, 
12.2370004653931, 12.5150003433228, 12.6669998168945, 12.8570003509521, 
13.125, 13.3369998931885, 13.496000289917, 13.5900001525879, 
13.7390003204346, 13.8459997177124, 14.0220003128052, 14.1359996795654, 
11.6099996566772, 11.7600002288818, 12.0319995880127, 12.3039999008179, 
12.5880002975464, 12.8380002975464, 13.0570001602173, 13.1979999542236, 
13.4340000152588, 13.6269998550415, 13.793999671936, 13.8680000305176, 
13.9689998626709, 14.0900001525879, 14.2679996490479, 14.3549995422363, 
14.4860000610352, 14.793999671936, 15.043999671936, 15.2620000839233, 
11.6070003509521, 11.9060001373291, 12.2030000686646, 12.4940004348755, 
12.8889999389648, 13.2290000915527, 13.375, 13.4619998931885, 
13.664999961853, 13.8579998016357, 14.0129995346069, 14.0860004425049, 
14.1379995346069, 14.3249998092651, 14.3459997177124, 14.4490003585815, 
14.5900001525879, 14.8699998855591, 15.1409997940063, 11.878999710083, 
12.1780004501343, 12.4379997253418, 12.8030004501343, 13.1579999923706, 
13.4519996643066, 13.5649995803833, 13.6529998779297, 13.8809995651245, 
14.0550003051758, 14.1120004653931, 14.2650003433228, 14.3520002365112, 
14.3420000076294, 14.3690004348755, 14.4619998931885, 14.6700000762939, 
14.9670000076294, 15.2320003509521, 12.1070003509521, 12.3439998626709, 
12.6859998703003, 12.9940004348755, 13.2740001678467, 13.5139999389648, 
13.6049995422363, 13.7229995727539, 13.8760004043579, 14.0380001068115, 
14.1789999008179, 14.3889999389648, 14.3929996490479, 14.4090003967285, 
14.3549995422363, 14.4449996948242, 14.6510000228882, 14.9829998016357, 
15.293999671936, 12.3800001144409, 12.6680002212524, 12.923999786377, 
13.2270002365112, 13.3610000610352, 13.5109996795654, 13.7910003662109, 
13.9729995727539, 14.1040000915527, 14.3470001220703, 14.4219999313354, 
14.4060001373291, 14.4219999313354, 14.4040002822876, 14.4350004196167, 
14.4619998931885, 14.5900001525879, 14.996000289917, 15.3769998550415, 
12.6960000991821, 12.8450002670288, 13.1099996566772, 13.4630002975464, 
13.5509996414185, 13.6300001144409, 14.0089998245239, 14.2530002593994, 
14.4440002441406, 14.6350002288818, 14.6540002822876, 14.5, 14.4350004196167, 
14.4219999313354, 14.4890003204346, 14.5830001831055, 14.6809997558594, 
15.1990003585815, 15.5290002822876, 12.8360004425049, 13.0920000076294, 
13.371000289917, 13.6719999313354, 14.0069999694824, 14.3039999008179, 
14.5790004730225, 14.6990003585815, 14.7709999084473, 14.7510004043579, 
14.6890001296997, 14.6269998550415, 14.5979995727539, 14.6450004577637, 
14.7580003738403, 14.9399995803833, 15.326000213623, 15.6669998168945, 
12.9650001525879, 13.2700004577637, 13.5939998626709, 13.9060001373291, 
14.2469997406006, 14.5120000839233, 14.6070003509521, 14.7679996490479, 
14.8830003738403, 14.8680000305176, 14.8809995651245, 14.9049997329712, 
14.9270000457764, 14.9340000152588, 14.9729995727539, 15.1009998321533, 
15.4180002212524, 15.8330001831055, 14.1990003585815, 14.4530000686646, 
14.6389999389648, 14.8489999771118, 14.9809999465942, 15.0150003433228, 
15.0030002593994, 15.0109996795654, 15.1180000305176), year = c(1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 1980L, 
1980L, 1980L, 1980L, 1980L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 
1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L, 1981L
), month = c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L)), sfc_columns = c("x", "y"), class = "data.frame", row.names = c(NA, 
-352L))

Code:

    library(tidyverse)
     library(patchwork)

# Define a function to compute R^2 and the formula
get_formula = function(model) {
  
  broom::tidy(model)[, 1:2] %>%
    mutate(sign = ifelse(sign(estimate) == 1, ' + ', ' - ')) %>% #coeff signs
    mutate_if(is.numeric, ~ abs(round(., 2))) %>% #for improving formatting
    mutate(a = ifelse(term == '(Intercept)', paste0('y ~ ', estimate), paste0(sign, estimate, ' * ', term))) %>%
    summarise(formula = paste(a, collapse = '')) %>%
    as.character
  
}        
        # First see it visually
        gg1 = df %>%
      ggplot(aes(x = year, y = TMin)) +
      geom_point(aes(color = "Temperature"), size = 2, shape = 1, alpha = 0.1) +
      geom_smooth(method = lm, aes(linetype = "LM"), se = FALSE, color = "red") +
      scale_linetype_manual(values = 2, name = NULL) +
      scale_colour_manual(values = "deepskyblue4", name = "Legend") +
      theme(text = element_text(size = 16)) +
      xlab("Year") +
      ylab("Mean Temperature (\u00B0C)") +
      ggtitle("February 1980-1981 Historical Change")+
      guides(color = guide_legend(override.aes = list(alpha = 0.5), order = 1))
    
    # Model and label formula and R^2
    
    lm(TMin ~ year, data = df) -> model_df
    get_formula(model_df)
    
    scales::percent(summary(model_df)$r.squared, accuracy = 0.01) -> r_model_TMin
    summary(model_df)$r.squared -> r_squared_TMin
    r_squared_TMin = round(r_squared_TMin, digits = 4)
    
    #Now we need to add the text to the plot:
    pw1 = gg1 + 
      geom_text(x = 1980.09, y = 15.9,
                label = paste0("Formula = ", get_formula(model_df)),
                color = 'red') +
      geom_text(x = 1980, y = 15.7,
                label = paste0("R\U00B2 = ", r_squared_TMin),
      
              color = 'blue')
    # Check
    pw
    
    # Repeating the same code and data to create 3 other plots just for the sake of this question
    
    pw2 = pw1
    
    pw3 = pw1
    
    pw4 = pw1
    
    # Combine via patchwork
    
    pw1 + pw2 + pw3 + pw4  + plot_layout(guides = 'collect') # ggtext gets misplaced...

Solution

  • The "misplaced" labels are a consequence of using absolute data values to place the labels. As a consequence the position of the labels may look right when plotting just one plot but may overlap if you glue four plots together (The same issue may occur when you export your plot depending on the size of the exported plot.).

    In your case a possible fix would be to position the labels on top of each other by setting the vertical alignment via vjust, i.e. use the same y position for both labels but set vjust = 0 (or -.1 to add some padding) for the top label and vjust = 1 (or 1.1) for the bottom label:

    Note: I dropped the get_formula part as it resulted in an error when running your code and is IMHO not important for the issue. I also used the same x value and set hjust=0 for both labels.

    pw1 = gg1 + 
      geom_text(x = 1980, y = 15.8,
                label = paste0("Formula"),
                color = 'red',
                vjust = -.1,
                hjust = 0
                ) +
      geom_text(x = 1980, y = 15.8,
                label = paste0("R\U00B2 = ", r_squared_TMin),
                vjust = 1.1,
                hjust = 0,
                color = 'blue')
    
    pw1 + pw1 + pw1 + pw1  + plot_layout(guides = 'collect')
    

    enter image description here

    UPDATE And here is the code for using geom_label:

    pw1 = gg1 + 
      geom_label(x = 1980, y = 15.8,
                label = paste0("Formula"),
                color = 'red',
                vjust = 0,
                hjust = 0,
                fill = NA,
                label.size = 0,
                label.padding = unit(1, "pt")
                ) +
      geom_label(x = 1980, y = 15.8,
                label = paste0("R\U00B2 = ", r_squared_TMin),
                vjust = 1,
                hjust = 0,
                fill = NA,
                label.size = 0,
                label.padding = unit(1, "pt"),
                color = 'blue')
    
    pw1 + pw1 + pw1 + pw1  + plot_layout(guides = 'collect')
    

    enter image description here