Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ggplot - Multiple legends arrangement

I want to arrange mutiple legend in ggplot with multiple rows and columns. However currently, from the documentation I can only decide there direction or manipulate rows/columns within 1 legend. Am I overlook something? Thanks for any reference point to the solution. Here is the sample code and what I have done and the expect result.

data <- seq(1000, 4000, by=1000)
colorScales <- c("#c43b3b", "#80c43b", "#3bc4c4", "#7f3bc4")
names(colorScales) <- data
ggplot() +
    geom_point(aes(x=data, y=data, color=as.character(data), fill=data, size=data),
               shape=21) +
    scale_color_manual(name="Legend 1",
                      values=colorScales) +
    scale_fill_gradientn(name="Legend 2",
                          labels=comma, limits=c(0, max(data)),
                          colours=rev(c("#000000", "#FFFFFF", "#BA0000")),
                         values=c(0, 0.5, 1)) +
    scale_size_continuous(name="Legend 3") +
    theme(legend.direction = "vertical", legend.box = "vertical")

Output vertical legend: enter image description here

ggplot() +
    geom_point(aes(x=data, y=data, color=as.character(data), fill=data, size=data),
               shape=21) +
    scale_color_manual(name="Legend 1",
                       values=colorScales) +
    scale_fill_gradientn(name="Legend 2",
                         labels=comma, limits=c(0, max(data)),
                         colours=rev(c("#000000", "#FFFFFF", "#BA0000")), 
                         values=c(0, 0.5, 1)) +
    scale_size_continuous(name="Legend 3") +
    theme(legend.direction = "vertical", legend.box = "horizontal")

Output horizontal legend enter image description here

ggplot() +
    geom_point(aes(x=data, y=data, color=as.character(data), fill=data, size=data),
               shape=21) +
    scale_color_manual(name="Legend 1",
                       values=colorScales) +
    scale_fill_gradientn(name="Legend 2",
                         labels=comma, limits=c(0, max(data)),
                         colours=rev(c("#000000", "#FFFFFF", "#BA0000")), 
                         values=c(0, 0.5, 1)) +
    guides(colour = guide_legend(nrow = 2, byrow = T, override.aes=list(size=4))) +
    guides(size = guide_legend(nrow = 2, byrow = T)) +
    scale_size_continuous(name="Legend 3") +
    theme(legend.direction = "vertical", legend.box = "vertical")

Output legend with vertical layout, 2 columns within each legend: enter image description here

What I want is this:

enter image description here

like image 927
Sinh Nguyen Avatar asked Aug 28 '18 14:08

Sinh Nguyen


People also ask

How do I change the order of my legend in ggplot2?

You can use the following syntax to change the order of the items in a ggplot2 legend: scale_fill_discrete(breaks=c('item4', 'item2', 'item1', 'item3', ...) The following example shows how to use this syntax in practice.

How do I change the position of my legend in R?

Control legend position with legend. You can place the legend literally anywhere. To put it around the chart, use the legend. position option and specify top , right , bottom , or left . To put it inside the plot area, specify a vector of length 2, both values going between 0 and 1 and giving the x and y coordinates.

How do I get rid of the legend in ggplot2?

Example 1: Remove All Legends in ggplot2 We simply had to specify legend. position = “none” within the theme options to get rid of both legends.

How do I add a legend in ggplot2?

Adding a legend If you want to add a legend to a ggplot2 chart you will need to pass a categorical (or numerical) variable to color , fill , shape or alpha inside aes . Depending on which argument you use to pass the data and your specific case the output will be different.


1 Answers

The idea is to create each plot individually (color, fill & size) then extract their legends and combine them in a desired way together with the main plot.

See more about the cowplot package here & the patchwork package here

library(ggplot2)
library(cowplot)   # get_legend() & plot_grid() functions
library(patchwork) # blank plot: plot_spacer()

data <- seq(1000, 4000, by = 1000)
colorScales <- c("#c43b3b", "#80c43b", "#3bc4c4", "#7f3bc4")
names(colorScales) <- data

# Original plot without legend
p0 <- ggplot() +
  geom_point(aes(x = data, y = data, 
                 color = as.character(data), fill = data, size = data),
             shape = 21
  ) +
  scale_color_manual(
    name = "Legend 1",
    values = colorScales
  ) +
  scale_fill_gradientn(
    name = "Legend 2",
    limits = c(0, max(data)),
    colours = rev(c("#000000", "#FFFFFF", "#BA0000")),
    values = c(0, 0.5, 1)
  ) +
  scale_size_continuous(name = "Legend 3") +
  theme(legend.direction = "vertical", legend.box = "horizontal") +
  theme(legend.position = "none")

# color only
p1 <- ggplot() +
  geom_point(aes(x = data, y = data, color = as.character(data)),
             shape = 21
  ) +
  scale_color_manual(
    name = "Legend 1",
    values = colorScales
  ) +
  theme(legend.direction = "vertical", legend.box = "vertical")

# fill only
p2 <- ggplot() +
  geom_point(aes(x = data, y = data, fill = data),
             shape = 21
  ) +
  scale_fill_gradientn(
    name = "Legend 2",
    limits = c(0, max(data)),
    colours = rev(c("#000000", "#FFFFFF", "#BA0000")),
    values = c(0, 0.5, 1)
  ) +
  theme(legend.direction = "vertical", legend.box = "vertical")

# size only
p3 <- ggplot() +
  geom_point(aes(x = data, y = data, size = data),
             shape = 21
  ) +
  scale_size_continuous(name = "Legend 3") +
  theme(legend.direction = "vertical", legend.box = "vertical")

Get all legends

leg1 <- get_legend(p1)
leg2 <- get_legend(p2)
leg3 <- get_legend(p3)

# create a blank plot for legend alignment 
blank_p <- plot_spacer() + theme_void()

Combine legends

# combine legend 1 & 2
leg12 <- plot_grid(leg1, leg2,
                   blank_p,
                   nrow = 3
)

# combine legend 3 & blank plot
leg30 <- plot_grid(leg3, blank_p,
                   blank_p, 
                   nrow = 3
)

# combine all legends
leg123 <- plot_grid(leg12, leg30,
                    ncol = 2
)

Put everything together

final_p <- plot_grid(p0,
                     leg123,
                     nrow = 1,
                     align = "h",
                     axis = "t",
                     rel_widths = c(1, 0.3)
)

print(final_p)

Created on 2018-08-28 by the reprex package (v0.2.0.9000).

like image 199
Tung Avatar answered Oct 01 '22 17:10

Tung