Reputation: 320
I am wondering if it is possible to create a completely customized legend for a ggplot figure, that does not take into consideration any of the shapes, sizes, column names, etc. used in the given figure. It seems strange that this may not be the case, given that complex data sets can be difficult to rename, and that adding text to ggplot figure axes, annotations and labels is so straightforward. Can this perhaps be added to a ggplot object, in the same way you might add a theme? Let's say I wanted to have a legend that was titled "Different fruit", the three variables were "Apple", "Banana" and "Mango," and the three symbols associated with them were a filled black circle, a hollow circle, and a hollow triangle.
Here is some data I was playing around with:
library(ggplot2)
library(dplyr)
data_dna <- DNase
plot_dna <- ggplot(data_dna, aes(x = conc, y = density)) + geom_point()
plot_dna + theme(legend.position = c(2, 2), legend.text = element_text(size = 15))
This doesn't even succesfully produce a legend at all. Please let me know if you have any leads on this.
Upvotes: 1
Views: 478
Reputation: 37993
Here is a hacky solution I came up with. It draws an invisible geom layer that initialises a dummy aesthetic and associated scale. Not very flexible, but should do the trick.
library(ggplot2)
library(rlang)
#> Warning: package 'rlang' was built under R version 4.1.1
data_dna <- DNase
plot_dna <- ggplot(data_dna, aes(x = conc, y = density)) + geom_point()
dummy_guide <- function(
labels = NULL,
...,
title = NULL,
key = draw_key_point,
guide_args = list()
) {
# Capture arguments
aesthetics <- list(...)
n <- max(lengths(aesthetics), 0)
labels <- labels %||% seq_len(n)
# Overrule the alpha = 0 that we use to hide the points
aesthetics$alpha <- aesthetics$alpha %||% rep(1, n)
# Construct guide
guide_args$override.aes <- guide_args$override.aes %||% aesthetics
guide <- do.call(guide_legend, guide_args)
# Allow dummy aesthetic
update_geom_defaults("point", list(dummy = "x"))
dummy_geom <- geom_point(
data = data.frame(x = rep(Inf, n), y = rep(Inf, n),
dummy = factor(labels)),
aes(x, y, dummy = dummy), alpha = 0, key_glyph = key
)
dummy_scale <- discrete_scale(
"dummy", "dummy_scale", palette = scales::identity_pal(), name = title,
guide = guide
)
list(dummy_geom, dummy_scale)
}
Adding this without any arguments creates nothing.
plot_dna + dummy_guide()
By default, it creates keys as points.
plot_dna + dummy_guide(
labels = c("Apple", "Banana", "Mango"),
shape = c(16, 21, 24),
title = "Different Fruit"
)
You can change to key to something else.
plot_dna + dummy_guide(
labels = c("Foo", "Bar", "Baz"),
fill = c("blue", "green", "red"),
colour = NA,
title = "Metasyntactic variables",
key = draw_key_polygon
)
Created on 2022-02-03 by the reprex package (v2.0.1)
Upvotes: 3