Reputation: 3237
I'm aware that scale_*_*(drop = TRUE)
can be used to drop empty factor levels from a legend. Perhaps counterintuitively, I'm trying to drop used levels from plot.
As you may have guessed, it's a slightly hack-y use case: I'm using invisible bars with geom_bar
to offset 'floating' likert response visualisations. I'm not interested in frame-challenges or alternative approaches to this problem, I'm asking specifically about how to drop a used level from the legend.
The code below reproduces a very simple version of my visualisation. It works well enough, but the legend is offset very slightly from the centre (this notices more in the 'real' visualisation). I would like to drop the 'invisible' level to present this. I'm aware that I could use numeric arguments to legend.position
to re-centre the whole thing, but that's fiddly and non-generalisable.
## libraries ---
require(ggplot2)
#> Loading required package: ggplot2
require(dplyr)
#> Loading required package: dplyr
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
## data ---
plotData <- tibble(label =
factor(c("", "strawberries", "blueberries", "", "strawberries", "blueberries"),
levels = c("strawberries", "blueberries", ""), ordered = TRUE),
value = c(30, 40, 20, 15, 30, 15),
bowl = factor(c("bowl1", "bowl1", "bowl1", "bowl2", "bowl2", "bowl2")))
## plot ---
### Specs for the legend
legendSpecs <- guide_legend(nrow = 1, label.position = "bottom",
reverse = TRUE, title = NULL)
### desired plot
ggplot(plotData, aes(x = value, y = bowl,
fill = label, colour = label)) +
geom_bar(stat = "identity", position = "stack") +
scale_fill_manual(values = c("blue", "red", NA), guide = legendSpecs) +
scale_colour_manual(values = c("black", "black", NA), guide = legendSpecs) +
theme_minimal() +
theme(legend.position = "bottom")
Demonstrating the small offset in the legend that I'm trying to get rid of:
### demonstrating legend offset
ggplot(plotData, aes(x = value, y = bowl,
fill = label, colour = label)) +
geom_bar(stat = "identity", position = "stack") +
scale_fill_manual(values = c("blue", "red", NA), guide = legendSpecs) +
scale_colour_manual(values = c("black", "black", "black"), guide = legendSpecs) +
theme_minimal() +
theme(legend.position = "bottom")
Created on 2021-06-30 by the reprex package (v2.0.0)
Upvotes: 3
Views: 124
Reputation: 124183
This could be achieved by setting the breaks
of the scale to include only the desired categories:
## libraries ---
require(ggplot2)
require(dplyr)
## data ---
plotData <- tibble(label =
factor(c("", "strawberries", "blueberries", "", "strawberries", "blueberries"),
levels = c("strawberries", "blueberries", ""), ordered = TRUE),
value = c(30, 40, 20, 15, 30, 15),
bowl = factor(c("bowl1", "bowl1", "bowl1", "bowl2", "bowl2", "bowl2")))
## plot ---
### Specs for the legend
legendSpecs <- guide_legend(nrow = 1, label.position = "bottom",
reverse = TRUE, title = NULL)
### desired plot
ggplot(plotData, aes(x = value, y = bowl,
fill = label, colour = label)) +
geom_bar(stat = "identity", position = "stack") +
scale_fill_manual(values = c("blue", "red", NA), na.value = NA,
guide = legendSpecs, breaks = c("blueberries", "strawberries")) +
scale_colour_manual(values = c("black", "black", NA), , na.value = NA,
guide = legendSpecs,
breaks = c("blueberries", "strawberries")) +
theme_minimal() +
theme(legend.position = "bottom")
Upvotes: 1