Automate labels in the legend with ggplot

Hi, I'm creating many similar maps based on different variables. So far manually editing the legend labels has taken a lot of time, so I'm wondering if there're easier ways to automate legend labels without manual editing.

To illustrate my point, I'm using an US earthquake data available in library(usmap). This is a publicly available data in usmap.

#by loading the usmap package, you will find the earthquake data
library(usmap)
eq_transformed <- usmap_transform(earthquakes)

# say I want to transform the variable mag to a quartile, and map based on the quartile. note this is not my real data, so the map below will look weird

library(dvmisc)
eq_transformed$magqt<-quant_groups(eq_transformed$mag,4)
table(eq_transformed$magqt)
#the quartiles are
#[2.5,2.67] (2.67,2.9] (2.9,3.33] (3.33,7.1]  
# 591        545        562        556       

ggplot()+
  geom_point(data=eq_transformed, aes(x=lon.1, y=lat.1,fill=magqt))+
  theme_void()+
  scale_fill_manual( values=c("black", "blue", "grey","red"),
                     #here I need to manually input quartile thresholds based on the output, and also need to change it to percentage form
                     labels=c("2.5%-2.67%","2.68%-2.9%","2.91%-3.33%","3.34%-7.1%"))+
  theme(legend.position=c(0.8,0.85), 
        legend.background = element_blank(),
        legend.box.background = element_rect(colour = "black"))

Is there a way I can keep the legend exactly it is while not have to manually input the values? The only function that I think could be helpful is the mutate paste0. But I don't know how to make it work with the labels function within scale.

Any advice is appreciated!

Thanks for your example - I am using the separate function to split the labels and then create the label type you want. I also changed to use colour rather than fill for the points.

#by loading the usmap package, you will find the earthquake data
library(usmap)
eq_transformed <- usmap_transform(earthquakes)

# say I want to transform the variable mag to a quartile, and map based on the quartile. note this is not my real data, so the map below will look weird

library(dvmisc)
#> Loading required package: rbenchmark
#> Loading required package: dplyr
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
eq_transformed$magqt<-quant_groups(eq_transformed$mag,4)
#> Observations per group: 591, 545, 562, 556. 0 missing.

library(tidyverse)
labelbreaks <- tibble(origlev=levels(eq_transformed$magqt)) %>%
  mutate(lev=str_replace_all(origlev, "\\(|\\[|\\]", "")) %>%
  separate(lev, into=c("levlow", "levhi"), sep=",", convert=TRUE) %>%
  mutate(Label=str_c(levlow, "%-", levhi, "%")) %>%
  arrange(levlow)
  
labelbreaks
#> # A tibble: 4 x 4
#>   origlev    levlow levhi Label     
#>   <chr>       <dbl> <dbl> <chr>     
#> 1 [2.5,2.67]   2.5   2.67 2.5%-2.67%
#> 2 (2.67,2.9]   2.67  2.9  2.67%-2.9%
#> 3 (2.9,3.33]   2.9   3.33 2.9%-3.33%
#> 4 (3.33,7.1]   3.33  7.1  3.33%-7.1%

labels_range <- labelbreaks %>% pull(Label)

ggplot()+
  geom_point(data=eq_transformed, aes(x=lon.1, y=lat.1,colour=magqt))+
  theme_void()+
  scale_colour_manual( values=c("black", "blue", "grey","red"),
                     labels=labels_range)+
  theme(legend.position=c(0.8,0.85), 
        legend.background = element_blank(),
        legend.box.background = element_rect(colour = "black"))

Created on 2020-05-15 by the reprex package (v0.3.0)

1 Like

Thank you very much @StatSteph for your help! Your code has perfectly resolved my problem. I really appreciate your time on providing the code and support!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.