nimliug
nimliug

Reputation: 391

Custom ggplot legend by group

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 !

Upvotes: 2

Views: 1446

Answers (1)

stefan
stefan

Reputation: 123783

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))

Upvotes: 4

Related Questions