I am creating GIS maps for DC using ggplot in R. I am trying to customize my legend bar and labels. I can move legend keys but not the label using gtable_filter. I would like to move the last label '1' near it's legend bar like other labels. Any help appreciated. Image of the map
I am using the below R code :
Data set looks like below
    head(d1930)
R Output:
     Simple feature collection with 6 features and 355 fields
            geometry type:  MULTIPOLYGON
            dimension:      XY
            bbox:           xmin: -77.0823 ymin: 38.89061 xmax: -77.0446 ymax: 38.94211
            epsg (SRID):    4326
            proj4string:    +proj=longlat +datum=WGS84 +no_defs
              fipsstate fipscounty  tract NHGISST NHGISCTY      GISJOIN    GISJOIN2 SHAPE_AREA SHAPE_LEN  X  GISJOIN.x.1 year cenv1_1 cenv8_1
            1        11        001 000001     110     0010 G11000100001 11000100001    1953567  8965.853  1 G11001000001 1930    7889    5885
            2        11        001 000002     110     0010 G11000100002 11000100002    1345844  5668.739 10 G11001000002 1930    6250    5164
       # # borrowed map theme and code from here
        # # https://timogrossenbacher.ch/2016/12/beautiful-thematic-maps-with-ggplot2-only/
            theme_map <- function(...) {
              theme_minimal() +
                theme(
                  text = element_text(family = "Ubuntu Regular", color = "#22211d"),
                  axis.line = element_blank(),
                  axis.text.x = element_blank(),
                  axis.text.y = element_blank(),
                  axis.ticks = element_blank(),
                  axis.title.x = element_blank(),
                  axis.title.y = element_blank(),
                  # panel.grid.minor = element_line(color = "#ebebe5", size = 0.2),
                  panel.grid.major = element_line(color = "white", size = 0.2),
                  panel.grid.minor = element_blank(),
                  plot.background = element_rect(fill = "white", color = NA),
                  panel.background = element_rect(fill = "white", color = NA),
                  legend.background = element_rect(fill = "white", color = NA),
                  panel.border = element_blank(),
                  ...
                )
            }
    # create the color vector
        my.cols <- brewer.pal(4, "Blues")
    # compute labels
        labels <- c()
    # put manual breaks as desired
        brks <- c(0,0.15,0.5,0.85,1)
    # round the labels (actually, only the extremes)
        for(idx in 1:length(brks)){
          labels <- c(labels,round(brks[idx + 1], 2))
        }
    # put labels into label vector
        labels <- labels[1:length(labels)-1]
    # define a new variable on the data set just as above
        d1930$brks <- cut(d1930$pAA, 
                          breaks = brks, 
                          include.lowest = TRUE, 
                          labels = labels)
    # define breaks scale and labels scales
        brks_scale <- levels(d1930$brks)
        labels_scale <- rev(brks_scale)
    # draw the plot with legend at the bottom
        p <- ggplot(d1930) + 
          geom_sf(aes(fill=brks),colour = "white")+
          coord_sf() +
          theme_map() +
          theme(legend.position = "bottom",legend.background = element_rect(color = NA)) 
    # provide manual scale and colors to the graph
    tester <- p +
          # now we have to use a manual scale, 
          # because only ever one number should be shown per label
          scale_fill_manual(
            # in manual scales, one has to define colors, well, we have done it earlier
            values = my.cols,
            breaks = rev(brks_scale),
            name = "Share of Population African American",
            drop = FALSE,
            labels = labels_scale,
            guide = guide_legend(
              direction = "horizontal",
              keyheight = unit(2.5, units = "mm"),
              keywidth = unit(85 / length(labels), units = "mm"),                      title.position = 'top',
              # shift the labels around, the should be placed 
              # exactly at the right end of each legend key
              title.hjust = 0.5,
              label.hjust = 1,                         ### change here 
              nrow = 1,
              byrow = T,
              # also the guide needs to be reversed
              reverse = T,
              label.position = "bottom"
            )
          )
        tester
        library(grid)
        library(gtable)
        extendLegendWithExtremes <- function(p){
          p_grob <- ggplotGrob(p)
          legend <- gtable_filter(p_grob, "guide-box")
          legend_grobs <- legend$grobs[[1]]$grobs[[1]]
          print(legend_grobs)
          # grab the first key of legend
          legend_first_key <- gtable_filter(legend_grobs, "key-3-1-1")
          legend_first_key$widths <- unit(2, units = "cm")
          # modify its width and x properties to make it longer
          legend_first_key$grobs[[1]]$width <- unit(1, units = "cm")
          legend_first_key$grobs[[1]]$x <- unit(1.6, units = "cm")              
          # last key of legend
          legend_last_key <- gtable_filter(legend_grobs, "key-3-4-1")
          legend_last_key$widths <- unit(2, units = "cm")
          # analogous
          legend_last_key$grobs[[1]]$width <- unit(1, units = "cm")
          legend_last_key$grobs[[1]]$x <- unit(0.5, units = "cm")
          # grab the last label so we can also shift its position 
    # below code is where i am stuck as this is not shifting the label
          legend_last_label <- gtable_filter(legend_grobs, "label-5-4")
          legend_last_label$widths <- unit(20, units = "cm")
          legend_last_label$grobs[[1]]$x <- unit(-10.1, units = "cm")
          legend_last_label$grobs[[1]]$width <- unit(10, units = "cm")
    # Insert new color legend back into the combined legend
          legend_grobs$grobs[legend_grobs$layout$name == "key-3-1-1"][[1]] <- 
            legend_first_key$grobs[[1]]
          legend_grobs$grobs[legend_grobs$layout$name == "key-3-4-1"][[1]] <- 
            legend_last_key$grobs[[1]]
          legend_grobs$grobs[legend_grobs$layout$name == "label-5-4"][[1]] <- 
            legend_last_label$grobs[[1]]  
          legend$grobs[[1]]$grobs[1][[1]] <- legend_grobs
          p_grob$grobs[p_grob$layout$name == "guide-box"][[1]] <- legend
          # the plot is now drawn using this grid function
          grid.newpage()
          grid.draw(p_grob)
          print(legend_grobs)
          # save the plot
          ggsave(paste0("~/Desktop/RA/",dateo,"_dc_1930.jpg"),
                              plot = p_grob, dpi = 300, width = 11, height = 8.5, units = c("in"))
        }
        extendLegendWithExtremes(tester)
				
                        
Might it be that you do not exactly catch the coordinate of the last label? For example
legend_last_label$grobs[[1]]$xisNULLand it should return1npc. Here is a way of how you can get to it:Maybe is safer to use the
gPaths of each grob to "catch" them and then edit them witheditGrobfunction. Here is an example applied on your plottester:The legend is somewhere at the bottom, identified as "guide-box.etc"
Your last label is mentioned as:
Now we need to build the
gPaths for each grob. Maybe there are easier ways, but here is one way:The path to the text of your label is:
So, having the path, we can edit the grob, that is, move the label to the left:
Further, you can edit the width and position of a key. Here is how to edit the right-most key:
Also, I think you should replace
labels <- labels[1:length(labels)-1]withlabels <- labels[-length(labels)]; otherwise I get an error fromcutfunction, when you buildd1930$brks