Jude
Jude

Reputation: 193

Show corresponding legend for second geom_point()

I am plotting three times with geom_point in the same plot but the second and third geom_point don't appear in the legend and I don't understand why. I looked at many posts but I can't find a solution that really works. My 2 original dataframes are different and I would prefer to keep it that way and not join them.

enter image description here

Either the cross (or the colour) appears on all the legend items or the second geom_point() is not mentionned to the legend. Here's my current code:

ggplot () +
  geom_point(data = data_1[data_1$River != "Roya",], aes(x = W_AC, y = BRI_mean_XS, shape = River, col = Type), size = 3) +
  geom_point(data = data_2, aes(x = W_m, y = BRI_norm, color = "Second geom_point "), shape = 4, size = 2.5) + 
  scale_shape_manual(values = c(15, 18, 17, 16)) +
  scale_colour_manual(values = c("blue4", "chocolate1", "darkcyan")) +
  geom_text(data = data_1[data_1$River != "Roya",], aes(x = W_AC, y = BRI_mean_XS, label = Year, vjust = -0.5, hjust = -0.5), show.legend = FALSE, size = 4) +
  scale_x_continuous(name = "aa") +
  scale_y_continuous(name = "bb") + 
  geom_point(data = data_1[data_1$River == "Roya",], aes(x = W_AC, y = BRI_mean_XS), shape = 16, col = "cornflowerblue", size = 3) +
  geom_text(data = data_1[data_1$River == "Roya",], aes(x = W_AC, y = BRI_mean_XS, label = Year, vjust = -0.5, hjust = -0.5), show.legend = F, size = 4) +
  theme_bw()

I tried also to specify the colour and shape in the scale_*_manual but the shape is not used in the plot. For example: scale_shape_manual(values = c(15, 18, 17, 16, 4)), 4 being for the second geom_point.

As I read on other posts, when values are specified in scale_*_manual, it should appear after in the legend but here it seems mixed up. Is it not possible to show a blue cross in the Type section or the River section ? Same for the third geom_point() (Roya) is it possible to draw a blue circle in the River section?

Here's a dput of my 2 dataframes:

data_1:

structure(list(River = c("Durance", "Durance", "Durance", "Durance",  "Roya", "Var", "Drac", "Drac", "Drac", "Drac", "Var", "Var",  "Mareta", "Mareta", "Mareta", "Mareta", "Var"), Type = c("Under restoration",  "Target", "Under restoration", "Target", "Witness", "Under restoration",  "Under restoration", "Target", "Under restoration", "Target",  "Target", "Under restoration", "Under restoration", "Under restoration",  "Target", "Target", "Under restoration"), Year = c(2017, 2017,  2012, 2012, 2018, 2005, 2011, 2011, 2018, 2018, 2012, 2018, 2005,  2013, 2005, 2013, 2012), BRI_mean_XS = c(0.0028, 0.0017, 0.0033, 
0.0018, 0.009, 0.0097, 0.0182, 0.0026, 0.0032, 0.0035, 0.0053, 
0.0016, 0.005, 0.0041, 0.0058, 0.0082, 0.0037), W_AC = c(296.522411128284, 
411.01376146789, 263.944186046512, 363.288990825688, 88.6420798065296, 
155.868223887175, 41.4430051813472, 138.772532188841, 105.525906735751, 
108.848484848485, 144.78431372549, 314.685764654033, 29.8791208791209, 
52.8, 33.6949152542373, 34.4661016949153, 149.838539375275)), row.names = c(NA, 
-17L), class = c("tbl_df", "tbl", "data.frame"))

data_2:

structure(list(SITE = c("AIGUES-C", "BUECH-AV", "ARRONDINE",  "ARVAN", "ASSE-BLIEUX", "ASSE-BLIEUX", "ASSE-AV", "ASSE-AM",  "ASSE-AM", "BES-BLEONE", "BES-BLEONE", "BES-DROME", "BES-DROME",  "BLEONE-AM", "BLEONE-AV", "BUECH-AV", "BUECH-AV", "DRANSE-MORZINE",  "DRANSE-MORZINE", "DROME-RECOUBEAU", "DROME-PONTQUART", "DROME-PONTQUART",  "EYGUES-R", "FIER", "GIFFRE", "JABRON", "PETIT-BUECH", "PETIT-BUECH",  "ROUBION", "SASSE", "SASSE", "SASSE", "SEVERAISSE", "SEVERAISSE",  "UBAYE", "VANCON", "VAR", "VENEON", "VERDON", "DRAC LIDAR1",  "DROME LIDAR1", "DROME LIDAR2", "DROME LIDAR3"), W_m = c(180, 
333.593594745271, 56, 78, 102, 58.8, 171.9, 202, 170, 132, 148,  76, 98, 99.9, 171.3, 214, 125, 63, 64, 137, 181, 39, 66, 91,  220, 120, 90, 103, 114, 182, 123, 139, 152, 38, 144, 58, 183,  193, 193,
103.3287640678, 170.959110791, 168.800988262, 133.13237116 ), BRI_norm = c(0.00238417932933424, 0.0019586918252209, 0.00592873427970417, 
0.00496998572378169, 0.00257768461027533, 0.00594823420965329, 
0.00196839869925125, 0.00110647254938539, 0.00129282468469599, 
0.00255415705319677, 0.00189636185539575, 0.00272918083912772, 
0.00362898036424863, 0.00240398604859984, 0.00158558538418367, 
0.00179786294819712, 0.0024557284827885, 0.00910376733031885, 
0.00534776094775883, 0.00392598083437978, 0.00240750522409946, 
0.00514878385829154, 0.00254279813562245, 0.00563806058644668, 
0.00119537585167636, 0.00458318564753459, 0.00595336684669024, 
0.00487895959784154, 0.00292014352039067, 0.00238157929363119, 
0.0025305005154242, 0.00243334672392244, 0.00211201916980846, 
0.007410716639085, 0.0035528851408779, 0.00991898865707844, 0.00350148630982832, 
0.00181290043814611, 0.00277563808425691, 0.00766507891511477, 
0.000968375521552066, 0.000999909065815609, 0.00107669687622853 )), row.names = c(NA, -43L), class = c("tbl_df", "tbl", "data.frame" ))

Upvotes: 1

Views: 818

Answers (2)

Martin C. Arnold
Martin C. Arnold

Reputation: 9668

I'm really not a big fan of the following approach (it would be more idiomatic to solve this using appropriate mappings) but you could solve this quickly by overriding the color / shape aesthetics in River and Type legends to your liking:

  1. Modify your third point layer by moving the shape aesthetic inside aes and map from River:
aes(x = W_AC, y = BRI_mean_XS, shape = River)
  1. Adjust the shape scale such that Roya is represented by a circle (16):
scale_shape_manual(values = c(15, 18, 17, 16, 16))
  1. Override the aesthetics in the legend using guides():
 + guides(
    color = guide_legend(
        override.aes = list(shape = c(4, 16, 16))
    ),
    shape = guide_legend(
        override.aes = list(color = c(rep("black", 3), "cornflowerblue", "black"))
    )
  )

Result:

enter image description here

Upvotes: 1

Andy Baxter
Andy Baxter

Reputation: 7626

I hope this is a helpful step forward, but not entirely sure if it completes the plot you're looking for. In essence there are two further steps you should take to get everything in legends and everything in order:

  • Anything you want to appear in the legends should be within each aes() call for each geom_point()
  • using the breaks = argument in the scale_*_manual() calls lets you both specify everything that should be displayed and the order it should be in.

Working with both of those, this might be the start of what you're looking for:

library(ggplot2)

# the parts of the plot I haven't changed (separated for clarity)

p_base <- ggplot () +
  geom_text(
    data = data_1[data_1$River != "Roya", ],
    aes(
      x = W_AC,
      y = BRI_mean_XS,
      label = Year,
      vjust = -0.5,
      hjust = -0.5
    ),
    show.legend = FALSE,
    size = 4
  ) +
  scale_x_continuous(name = "aa") +
  scale_y_continuous(name = "bb") +
  geom_text(
    data = data_1[data_1$River == "Roya", ],
    aes(
      x = W_AC,
      y = BRI_mean_XS,
      label = Year,
      vjust = -0.5,
      hjust = -0.5
    ),
    show.legend = F,
    size = 4
  ) +
  theme_bw()

# Parts I've changed

p_base + geom_point(
  data = data_1[data_1$River != "Roya",],
  aes(
    x = W_AC,
    y = BRI_mean_XS,
    shape = River,
    col = Type
  ),
  size = 3
) +
  geom_point(
    data = data_2,
    aes(
      x = W_m,
      y = BRI_norm,
      shape = "Second geom_point",
      color = "Second geom_point"
    ),
    size = 2.5
  ) +
  scale_shape_manual(
    breaks = c("Drac", "Durance", "Mareta", "Roya", "Var", "Second geom_point"),
    values = c(15, 18, 17, 16, 10, 4)
  ) +
  scale_colour_manual(
    breaks = c("Target", "Under restoration", "Second geom_point", "Roya"),
    values = c("blue4", "chocolate1", "darkcyan", "cornflowerblue")
  ) +
  geom_point(
    data = data_1[data_1$River == "Roya",],
    aes(
      x = W_AC,
      y = BRI_mean_XS,
      shape = "Roya",
      col = "Roya"
    ),
    size = 3
  )

Created on 2021-04-07 by the reprex package (v2.0.0)

Upvotes: 2

Related Questions