Lactuca
Lactuca

Reputation: 115

Creating three groups of legends in ggplot2 in R

I am plotting 5 elements in my graph:

So I am trying to create three legend titles as follows:

  1. Crime ("anti-social behaviour", "theft", "violence")

  2. Smooth conditional mean ("anti-social behaviour", "theft", "violence")

  3. no name ("Unemployment rate")

So far, I've managed to add the Crime legend.

However, no matter where I put add linetype = ", the smooth conditional means won't appear in the legend. Also, if I try to add labs(linetype = "LEGEND TITLE") after the three geom_smooth(), the unemployment rate legend title changes instead (as shown in the output below).

Here's the output (the dashed lines refer to the three geom_smooth(), and the colour matches the crime type they are calculating the smooth conditional mean of.

enter image description here

This is the code I used; as you can see, I tried adding linetype = both inside and outside aes(). It just won't show up in the legend regardless.

So the question is, where should I put linetype = "" so that it shows the name of each smooth conditional mean??

ggplot(mapping=aes(Date)) +
  geom_line(aes(y = Crime_occurrences, colour = Crime),
            size = 1, data = cr_grouped) + #this is the crime legend and it works a charm
  geom_line(lwd = 1, mapping = aes(x = Date, y = rescale(Unemployment.rate, to = out_range, 
                                                         from = in_range),
                                   linetype = "Unemployment rate"), #this shows up alright
            data = ur_grouped) +
  labs(linetype = "Legend") + #this shows up only if I delete labs() under the 3 geom_smooth()
  geom_smooth(method = 'lm',se=F, aes(x=Date,y = Crime_occurrences, group=1), 
              linetype = "123456", col = "darkgreen", lty = 6, data=smooth_theft)+ #ex outside aes()
  geom_smooth(method = 'lm',se=F, aes(x=Date,y = Crime_occurrences, group=1,
                                      linetype = "ABCD"), #example inside aes()
              col = "red", lty = 6, data=smooth_antisocial)+
  geom_smooth(method = 'lm',se=F, aes(x=Date,y = Crime_occurrences, group=1), 
              col = "blue3", lty = 6, data=smooth_violence)+
  labs(linetype = "Smooth Conditional Means") + #this renames the labs() created for unemployment
  scale_x_date(breaks = seq(as.Date("2019-01-01"), as.Date("2020-10-01"), by="1 month"),
               date_labels = '%m %Y') +
  scale_y_continuous(sec.axis = 
                       sec_axis(~ rescale(.x, to = in_range, from = out_range), 
                                name = "Unemployment Rate (%)")) +
  theme(axis.text.x=element_text(angle =- 90, vjust = 0.5))

Thanks for any help you can give!

DPUT:

cr_grouped

structure(list(Date = structure(c(17897, 17897, 17897, 17928, 
17928, 17928, 17956, 17956, 17956, 17987, 17987, 17987, 18017, 
18017, 18017, 18048, 18048, 18048, 18078, 18078, 18078, 18109, 
18109, 18109, 18140, 18140, 18140, 18170, 18170, 18170, 18201, 
18201, 18201, 18231, 18231, 18231, 18262, 18262, 18262, 18293, 
18293, 18293, 18322, 18322, 18322, 18353, 18353, 18353, 18383, 
18383, 18383, 18414, 18414, 18414, 18444, 18444, 18444, 18475, 
18475, 18475, 18506, 18506, 18506, 18536, 18536, 18536), class = "Date"), 
    Crime = c("Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences", 
    "Anti-social behaviour", "Theft", "Violence and sexual offences"
    ), Crime_occurrences = c(59426L, 90521L, 66296L, 61187L, 
    85416L, 61955L, 67810L, 93273L, 70843L, 68936L, 87633L, 66300L, 
    71379L, 89408L, 69906L, 72021L, 86315L, 71564L, 83705L, 86819L, 
    74969L, 78481L, 83309L, 69450L, 67932L, 81552L, 68740L, 69469L, 
    90307L, 70696L, 60692L, 87529L, 69011L, 53728L, 82404L, 69231L, 
    59571L, 88523L, 70824L, 57038L, 83460L, 69155L, 70861L, 71699L, 
    68956L, 135439L, 44984L, 58431L, 138529L, 47934L, 65947L, 
    102061L, 53208L, 70050L, 88014L, 62855L, 76773L, 91811L, 
    65687L, 76171L, 81958L, 67925L, 72268L, 84434L, 69627L, 70698L
    )), row.names = c(NA, -66L), groups = structure(list(Date = structure(c(17897, 
17928, 17956, 17987, 18017, 18048, 18078, 18109, 18140, 18170, 
18201, 18231, 18262, 18293, 18322, 18353, 18383, 18414, 18444, 
18475, 18506, 18536), class = "Date"), .rows = structure(list(
    1:3, 4:6, 7:9, 10:12, 13:15, 16:18, 19:21, 22:24, 25:27, 
    28:30, 31:33, 34:36, 37:39, 40:42, 43:45, 46:48, 49:51, 52:54, 
    55:57, 58:60, 61:63, 64:66), ptype = integer(0), class = c("vctrs_list_of", 
"vctrs_vctr", "list"))), row.names = c(NA, 22L), class = c("tbl_df", 
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"))

ur_grouped

structure(list(Date = structure(c(17897, 17928, 17956, 17987, 
18017, 18048, 18078, 18109, 18140, 18170, 18201, 18231, 18262, 
18293, 18322, 18353, 18383, 18414, 18444, 18475, 18506, 18536
), class = "Date"), Unemployment.rate = c(4.85019120720378, 4.87826349489932, 
4.72619911892442, 4.82962291533381, 4.78037962696207, 4.75317591530959, 
4.53739659597437, 4.58692391687679, 4.57052637882086, 4.56628766844258, 
4.60997237871127, 4.58039236078879, 4.73224909680535, 4.73446295980473, 
4.62619907452877, 4.44434845370539, 4.53780319184207, 4.46033205030955, 
4.57680473216631, 5.01205713295936, 5.42174180050248, 5.75623503556053
)), row.names = c(NA, -22L), class = c("tbl_df", "tbl", "data.frame"
))

OUT_RANGE and IN_RANGE [out_range can be adjusted manually, I usually do out_range[2] <- X to check what value fits best for scaling purposes]

out_range <- range(cr_grouped$Crime_occurrences) in_range <- range(ur_grouped$Unemployment.rate)


smooth_theft

structure(list(Date = structure(c(17897, 17928, 17956, 17987, 
18017, 18048, 18078, 18109, 18140, 18170, 18201, 18231, 18262, 
18293, 18322, 18353, 18383, 18414, 18444, 18475, 18506, 18536
), class = "Date"), Crime = c("Theft", "Theft", "Theft", "Theft", 
"Theft", "Theft", "Theft", "Theft", "Theft", "Theft", "Theft", 
"Theft", "Theft", "Theft", "Theft", "Theft", "Theft", "Theft", 
"Theft", "Theft", "Theft", "Theft"), Crime_occurrences = c(90521L, 
85416L, 93273L, 87633L, 89408L, 86315L, 86819L, 83309L, 81552L, 
90307L, 87529L, 82404L, 88523L, 83460L, 71699L, 44984L, 47934L, 
53208L, 62855L, 65687L, 67925L, 69627L)), row.names = c(NA, -22L
), groups = structure(list(Date = structure(c(17897, 17928, 17956, 
17987, 18017, 18048, 18078, 18109, 18140, 18170, 18201, 18231, 
18262, 18293, 18322, 18353, 18383, 18414, 18444, 18475, 18506, 
18536), class = "Date"), .rows = structure(list(1L, 2L, 3L, 4L, 
    5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 
    18L, 19L, 20L, 21L, 22L), ptype = integer(0), class = c("vctrs_list_of", 
"vctrs_vctr", "list"))), row.names = c(NA, -22L), class = c("tbl_df", 
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"))

smooth_antisocial:

structure(list(Date = structure(c(17897, 17928, 17956, 17987, 
18017, 18048, 18078, 18109, 18140, 18170, 18201, 18231, 18262, 
18293, 18322, 18353, 18383, 18414, 18444, 18475, 18506, 18536
), class = "Date"), Crime = c("Anti-social behaviour", "Anti-social behaviour", 
"Anti-social behaviour", "Anti-social behaviour", "Anti-social behaviour", 
"Anti-social behaviour", "Anti-social behaviour", "Anti-social behaviour", 
"Anti-social behaviour", "Anti-social behaviour", "Anti-social behaviour", 
"Anti-social behaviour", "Anti-social behaviour", "Anti-social behaviour", 
"Anti-social behaviour", "Anti-social behaviour", "Anti-social behaviour", 
"Anti-social behaviour", "Anti-social behaviour", "Anti-social behaviour", 
"Anti-social behaviour", "Anti-social behaviour"), Crime_occurrences = c(59426L, 
61187L, 67810L, 68936L, 71379L, 72021L, 83705L, 78481L, 67932L, 
69469L, 60692L, 53728L, 59571L, 57038L, 70861L, 135439L, 138529L, 
102061L, 88014L, 91811L, 81958L, 84434L)), row.names = c(NA, 
-22L), groups = structure(list(Date = structure(c(17897, 17928, 
17956, 17987, 18017, 18048, 18078, 18109, 18140, 18170, 18201, 
18231, 18262, 18293, 18322, 18353, 18383, 18414, 18444, 18475, 
18506, 18536), class = "Date"), .rows = structure(list(1L, 2L, 
    3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 
    16L, 17L, 18L, 19L, 20L, 21L, 22L), ptype = integer(0), class = c("vctrs_list_of", 
"vctrs_vctr", "list"))), row.names = c(NA, -22L), class = c("tbl_df", 
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"))

Upvotes: 1

Views: 58

Answers (1)

Duck
Duck

Reputation: 39585

Try next code. First install the ggnewscale package. I have removed the last piece of code as you do not shared the data for that smoothed option but adding that would not be an issue. Here the code:

library(ggnewscale)
#Plot
ggplot(mapping=aes(Date)) +
  geom_line(aes(y = Crime_occurrences, colour = Crime),
            size = 1, data = cr_grouped) +
  geom_line(lwd = 1, mapping = aes(x = Date,
                                   y = rescale(Unemployment.rate,
                                               to = out_range,
                                               from = in_range),
                                   linetype = "Unemployment rate"),
            data = ur_grouped) +
  labs(linetype = "Legend") +
  new_scale_color()+
  geom_smooth(method = 'lm',se=F,
              aes(x=Date,y = Crime_occurrences, group=1,
                  color='smooth_theft'), 
              lty = 6, data=smooth_theft)+
  geom_smooth(method = 'lm',se=F,
              aes(x=Date,y = Crime_occurrences, group=1,
                  color='smooth_antisocial'),
              lty = 6, data=smooth_antisocial)+
  labs(colour = "Smooth Conditional Means") + 
  scale_color_manual(values=c('darkgreen','red'))+
  scale_x_date(breaks = seq(as.Date("2019-01-01"), as.Date("2020-10-01"), by="1 month"),
               date_labels = '%m %Y') +
  scale_y_continuous(sec.axis = 
                       sec_axis(~ rescale(.x, to = in_range, from = out_range), 
                                name = "Unemployment Rate (%)")) +
  theme(axis.text.x=element_text(angle =- 90, vjust = 0.5))

Output:

enter image description here

Upvotes: 2

Related Questions