Search code examples
rggplot2legendlegend-properties

How to align the legend box to the middle of legend title in ggplot2?


By default the legend box/key is aligned to the left of the legend title. Since I have quite long legend title, I want to align it to the center instead. I have tried theme and guide_legend without any success. Any suggestion would be appreciated. Thanks!

  • Data

    df <- structure(list(Flow = c(0.992762, 0.802408, 0.9826, 0.754863, 
            0.174542, 0.056777), Coef = c(0.62, 0.49, 0.38, 0.59, 0.25, 0.67
            ), VeryLongLegendTitle = c(4.47680710313542, 18.8500193246859, 
            5.82742564783431, 23.3217237977105, 13.0155332302148, 88.4960885143824
            )), class = "data.frame", row.names = c(NA, -6L), .Names = c("Flow", 
            "Coef", "VeryLongLegendTitle"))
    
  • Code

    library(ggplot2)
    p1 <- ggplot(df, aes(x = Flow, y = Coef, color = VeryLongLegendTitle)) +
      xlab(NULL) + scale_x_continuous(limits = c(0.0, 1.0), breaks = c(0.25, 0.75)) +
      geom_point(size = 2, alpha = 0.8) + 
      theme_bw(base_size = 14) +
      theme(axis.text.x = element_text(angle = 0, vjust = 0.5))
    p1
    
    p1 + theme(legend.title.align = 0.5) 
    p1 + theme(legend.title = element_text(hjust = 0.5))
    p1 + guides(color = guide_legend(title.hjust = 0.5))
    
  • Plot enter image description here


Solution

  • Borrow the solution from this workaround

    library(ggplot2)
    library(gtable)
    library(grid)
    
    long1 <- ggplot(df, aes(x = Flow, y = Coef, color = VeryLongLegendTitle)) +
      xlab(NULL) + scale_x_continuous(limits = c(0.0, 1.0), breaks = c(0.25, 0.75)) +
      geom_point(size = 2, alpha = 0.8) + 
      theme_bw(base_size = 14) +
      theme(axis.text.x = element_text(angle = 0, vjust = 0.5))
    
    # extract legend
    g <- ggplotGrob(long1)
    grobs <- g$grobs
    legend_index <- which(sapply(grobs, function(x) x$name) == "guide-box")
    legend <- grobs[[legend_index]]
    
    # extract guides table
    guides_index <- which(sapply(legend$grobs, function(x) x$name) == "layout")
    guides <- legend$grobs[[guides_index]]
    
    # add extra column for spacing
    # guides$width[5] is the extra spacing from the end of the legend text
    # to the end of the legend title. If we instead distribute it 50:50 on
    # both sides, we get a centered legend
    guides <- gtable_add_cols(guides, 0.5*guides$width[5], 1)
    guides$widths[6] <- guides$widths[2]
    title_index <- guides$layout$name == "title"
    guides$layout$l[title_index] <- 2
    
    # reconstruct legend and write back
    legend$grobs[[guides_index]] <- guides
    g$grobs[[legend_index]] <- legend
    
    grid.newpage()
    grid.draw(g)
    

    Created on 2018-03-18 by the reprex package (v0.2.0).