Placing legends

Author

Michael Stadler, Charlotte Soneson

Summary

This document illustrates how to place legends in different positions in a ggplot.

Prepare data

Run the following code to load the data used in this document:

suppressPackageStartupMessages({
    library(dplyr)
    library(tibble)
    library(swissknife)
    library(ggplot2)
})

loadExampleData("mycars")
`mycars`: re-encoded version of `datasets::mtcars`
tibble(mycars)
# A tibble: 32 × 13
     mpg cyl    disp    hp  drat    wt  qsec    vs    am  gear  carb
   <dbl> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
 1  21   6      160    110  3.9   2.62  16.5     0     1     4     4
 2  21   6      160    110  3.9   2.88  17.0     0     1     4     4
 3  22.8 4      108     93  3.85  2.32  18.6     1     1     4     1
 4  21.4 6      258    110  3.08  3.22  19.4     1     0     3     1
 5  18.7 8      360    175  3.15  3.44  17.0     0     0     3     2
 6  18.1 6      225    105  2.76  3.46  20.2     1     0     3     1
 7  14.3 8      360    245  3.21  3.57  15.8     0     0     3     4
 8  24.4 4      147.    62  3.69  3.19  20       1     0     4     2
 9  22.8 4      141.    95  3.92  3.15  22.9     1     0     4     2
10  19.2 6      168.   123  3.92  3.44  18.3     1     0     4     4
# ℹ 22 more rows
# ℹ 2 more variables: engine_shape <fct>, transmission <fct>

Step 1 - construct basic plot

Code
gg <- ggplot(mycars, 
             aes(x = mpg, y = disp, color = cyl)) + 
    geom_point(size = 4) +
    scale_color_manual(values = c(`4` = "purple", `6` = "orange", 
                                  `8` = "forestgreen"), 
                       name = "Number of\ncylinders") + 
    labs(x = "Miles/gallon", y = "Displacement") + 
    theme_bw(base_size = 13)
gg

Step 2 - move legend to the bottom

Code
gg + theme(legend.position = "bottom")

Step 3 - move legend inside the canvas (top right corner)

Code
gg + theme(legend.position = "inside",
           legend.position.inside = c(0.97, 0.97),
           legend.justification = c(1, 1), 
           legend.background = element_rect(color = "black"),
           legend.title.position = "left")

Step 4 - hide specific legend

Use the cyl column for both color and shape, but only show the legend for the shape.

Code
ggplot(mycars, 
       aes(x = mpg, y = disp, color = cyl, shape = cyl)) + 
    geom_point(size = 4) +
    scale_color_manual(values = c(`4` = "purple", `6` = "orange", 
                                  `8` = "forestgreen"), 
                       name = "Number of\ncylinders") + 
    labs(x = "Miles/gallon", y = "Displacement") + 
    theme_bw(base_size = 13) + 
    guides(color = "none", 
           shape = guide_legend(title = "Number of\ncylinders"))

Step 5 - place different legends in different positions

Code
ggplot(mycars, 
       aes(x = mpg, y = disp, color = gear, shape = cyl)) + 
    geom_point(size = 4) +
    scale_color_continuous(name = "Number of\ngears") + 
    scale_shape_discrete(name = "Number of\ncylinders") + 
    labs(x = "Miles/gallon", y = "Displacement") + 
    theme_bw(base_size = 13) + 
    guides(color = guide_colorbar(position = "right"), 
           shape = guide_legend(position = "bottom"))

Session info

Code
sessioninfo::session_info()
─ Session info ───────────────────────────────────────────────────────────────
 setting  value
 version  R version 4.5.2 (2025-10-31)
 os       macOS Sequoia 15.7.1
 system   aarch64, darwin20
 ui       X11
 language (EN)
 collate  en_US.UTF-8
 ctype    en_US.UTF-8
 tz       Europe/Zurich
 date     2025-11-03
 pandoc   3.6.4 @ /usr/local/bin/ (via rmarkdown)
 quarto   1.7.28 @ /usr/local/bin/quarto

─ Packages ───────────────────────────────────────────────────────────────────
 package              * version date (UTC) lib source
 abind                  1.4-8   2024-09-12 [1] CRAN (R 4.5.0)
 Biobase                2.70.0  2025-10-29 [1] Bioconductor 3.22 (R 4.5.1)
 BiocGenerics           0.56.0  2025-10-29 [1] Bioconductor 3.22 (R 4.5.1)
 BiocParallel           1.44.0  2025-10-29 [1] Bioconductor 3.22 (R 4.5.1)
 cli                    3.6.5   2025-04-23 [1] CRAN (R 4.5.0)
 codetools              0.2-20  2024-03-31 [2] CRAN (R 4.5.2)
 DelayedArray           0.36.0  2025-10-29 [1] Bioconductor 3.22 (R 4.5.1)
 dichromat              2.0-0.1 2022-05-02 [1] CRAN (R 4.5.0)
 digest                 0.6.37  2024-08-19 [1] CRAN (R 4.5.0)
 dplyr                * 1.1.4   2023-11-17 [1] CRAN (R 4.5.0)
 evaluate               1.0.5   2025-08-27 [1] CRAN (R 4.5.1)
 farver                 2.1.2   2024-05-13 [1] CRAN (R 4.5.0)
 fastmap                1.2.0   2024-05-15 [1] CRAN (R 4.5.0)
 fs                     1.6.6   2025-04-12 [1] CRAN (R 4.5.0)
 generics               0.1.4   2025-05-09 [1] CRAN (R 4.5.0)
 GenomeInfoDb           1.46.0  2025-10-29 [1] Bioconductor 3.22 (R 4.5.1)
 GenomicRanges          1.62.0  2025-10-29 [1] Bioconductor 3.22 (R 4.5.1)
 ggplot2              * 4.0.0   2025-09-11 [1] CRAN (R 4.5.0)
 glue                   1.8.0   2024-09-30 [1] CRAN (R 4.5.0)
 gtable                 0.3.6   2024-10-25 [1] CRAN (R 4.5.0)
 htmltools              0.5.8.1 2024-04-04 [1] CRAN (R 4.5.0)
 htmlwidgets            1.6.4   2023-12-06 [1] CRAN (R 4.5.0)
 httr                   1.4.7   2023-08-15 [1] CRAN (R 4.5.0)
 IRanges                2.44.0  2025-10-29 [1] Bioconductor 3.22 (R 4.5.1)
 jsonlite               2.0.0   2025-03-27 [1] CRAN (R 4.5.0)
 KernSmooth             2.23-26 2025-01-01 [2] CRAN (R 4.5.2)
 knitr                  1.50    2025-03-16 [1] CRAN (R 4.5.0)
 labeling               0.4.3   2023-08-29 [1] CRAN (R 4.5.0)
 lattice                0.22-7  2025-04-02 [1] CRAN (R 4.5.0)
 lifecycle              1.0.4   2023-11-07 [1] CRAN (R 4.5.0)
 magrittr               2.0.4   2025-09-12 [1] CRAN (R 4.5.1)
 Matrix                 1.7-4   2025-08-28 [2] CRAN (R 4.5.2)
 MatrixGenerics         1.22.0  2025-10-29 [1] Bioconductor 3.22 (R 4.5.1)
 matrixStats            1.5.0   2025-01-07 [1] CRAN (R 4.5.0)
 pillar                 1.11.1  2025-09-17 [1] CRAN (R 4.5.0)
 pkgconfig              2.0.3   2019-09-22 [1] CRAN (R 4.5.0)
 png                    0.1-8   2022-11-29 [1] CRAN (R 4.5.0)
 purrr                  1.1.0   2025-07-10 [1] CRAN (R 4.5.1)
 R6                     2.6.1   2025-02-15 [1] CRAN (R 4.5.0)
 RColorBrewer           1.1-3   2022-04-03 [1] CRAN (R 4.5.0)
 Rcpp                   1.1.0   2025-07-02 [1] CRAN (R 4.5.0)
 rlang                  1.1.6   2025-04-11 [1] CRAN (R 4.5.0)
 rmarkdown              2.30    2025-09-28 [1] CRAN (R 4.5.0)
 rstudioapi             0.17.1  2024-10-22 [1] CRAN (R 4.5.0)
 S4Arrays               1.10.0  2025-10-29 [1] Bioconductor 3.22 (R 4.5.1)
 S4Vectors              0.48.0  2025-10-29 [1] Bioconductor 3.22 (R 4.5.1)
 S7                     0.2.0   2024-11-07 [1] CRAN (R 4.5.0)
 scales                 1.4.0   2025-04-24 [1] CRAN (R 4.5.0)
 Seqinfo                1.0.0   2025-10-29 [1] Bioconductor 3.22 (R 4.5.1)
 sessioninfo            1.2.3   2025-02-05 [1] CRAN (R 4.5.0)
 SparseArray            1.10.1  2025-10-31 [1] Bioconductor 3.22 (R 4.5.1)
 SummarizedExperiment   1.40.0  2025-10-29 [1] Bioconductor 3.22 (R 4.5.1)
 swissknife           * 0.44    2025-11-03 [1] Github (fmicompbio/swissknife@c69e512)
 tibble               * 3.3.0   2025-06-08 [1] CRAN (R 4.5.0)
 tidyselect             1.2.1   2024-03-11 [1] CRAN (R 4.5.0)
 UCSC.utils             1.6.0   2025-10-29 [1] Bioconductor 3.22 (R 4.5.1)
 usethis                3.2.1   2025-09-06 [1] CRAN (R 4.5.0)
 utf8                   1.2.6   2025-06-08 [1] CRAN (R 4.5.0)
 vctrs                  0.6.5   2023-12-01 [1] CRAN (R 4.5.0)
 withr                  3.0.2   2024-10-28 [1] CRAN (R 4.5.0)
 xfun                   0.54    2025-10-30 [1] CRAN (R 4.5.0)
 XVector                0.50.0  2025-10-29 [1] Bioconductor 3.22 (R 4.5.1)
 yaml                   2.3.10  2024-07-26 [1] CRAN (R 4.5.0)

 [1] /Users/stadler/Library/R/arm64/4.5/library/__bioc322
 [2] /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/library
 * ── Packages attached to the search path.

──────────────────────────────────────────────────────────────────────────────