Custom ggplot legend by group

Viewed 365

I want to create a graph like below but with a custom legend by group. I have two samples names A and B and a target (Y) associated. what I want is to group the legend with one side :
sample A : true vs obs
and other side
sample B : true vs obs
with the corresponding shape and color. Below, this is what I already had.

library(ggplot2)
sites = rep(seq(0.55,0.58,0.01), times = 4)
sites = sort(sites)

org = rep(c("Y_A", "Y_A_obs", "Y_b", "Y_b_obs"), times = 4)
values = rnorm(16)

df = data.frame(sites = sites, origine = org, values = values)

ggplot(df, aes(x=sites, y=values, color=origine)) + 
  geom_point(aes(shape=origine, color=origine), size=3)+
  scale_shape_manual(values=c(0, 15, 2, 17))+
  scale_color_manual(values=c("blue", "purple", "red", "orange"))

enter image description here

And this is what I want: enter image description here

Thanks for any help !

1 Answers

One option to achieve your desired result would be to make use of the ggnewscale package which allows for multiple scales and legends for the same aesthetic(s). Drawback of this method is that it doubles the lines of code:

library(ggplot2)
library(ggnewscale)

set.seed(123)

sites = rep(seq(0.55,0.58,0.01), times = 4)
sites = sort(sites)

org = rep(c("Y_A", "Y_A_obs", "Y_b", "Y_b_obs"), times = 4)
values = rnorm(16)

df = data.frame(sites = sites, origine = org, values = values)

ggplot() + 
  geom_point(data = subset(df, grepl("^Y_A", org)), aes(x=sites, y=values, shape=origine, color=origine), size=3)+
  scale_shape_manual(name = "A", values=c(Y_A = 0, Y_A_obs = 15), 
                     labels=c(Y_A = "y_true", Y_A_obs = "y_pred"), 
                     guide = guide_legend(order = 1))+
  scale_color_manual(name = "A", 
                     values=c(Y_A = "blue", Y_A_obs = "purple"), 
                     labels=c(Y_A = "y_true", Y_A_obs = "y_pred"), 
                     guide = guide_legend(order = 1)) +
  new_scale_color() +
  new_scale("shape") +
  geom_point(data = subset(df, grepl("^Y_b", org)), aes(x=sites, y=values, shape=origine, color=origine), size=3)+
  scale_shape_manual(name = "B", 
                     values=c(Y_b = 2, Y_b_obs = 17), 
                     labels=c(Y_b = "y_true", Y_b_obs = "y_pred"), 
                     guide = guide_legend(order = 2))+
  scale_color_manual(name = "B", 
                     values=c(Y_b = "red", Y_b_obs = "orange"), 
                     labels=c(Y_b = "y_true", Y_b_obs = "y_pred"),
                     guide = guide_legend(order = 2))

Related