Description
This problem is associated with the scale_fill_
and scale_color
functions, including their manual
versions, which contain the drop
argument. What is happening is that if you have data where any of the factors are not in use, and you are using drop = FALSE
, these factors appear in the legend, but without any associated color.
library(dplyr, warn.conflicts = FALSE)
library(ggplot2)
mtcars_tbl <- mtcars %>%
as_tibble() %>%
mutate(
cyl = factor(cyl,
levels = c("4", "6", "8", "10"))
)
mtcars_tbl %>%
ggplot(aes(mpg, wt)) +
geom_point(aes(colour = cyl)) +
scale_color_brewer(drop = FALSE, palette = "Dark2")
Created on 2024-07-11 with reprex v2.1.1
I understand that the operation of associated with drop = FALSE
has had continuous changes over time (#4511 , #4619 , #4723 , #5214), so I have tried different iterations on the above issues, but none of them work.
library(dplyr, warn.conflicts = FALSE)
library(ggplot2)
mtcars_tbl <- mtcars %>%
as_tibble() %>%
mutate(
cyl = factor(cyl,
levels = c("4", "6", "8", "10"))
)
# Colors manuals
colors <- RColorBrewer::brewer.pal(n = 4, name = "Dark2")
colors
#> [1] "#1B9E77" "#D95F02" "#7570B3" "#E7298A"
# With scale_color_manual
mtcars_tbl %>%
ggplot(aes(mpg, wt)) +
geom_point(aes(colour = cyl)) +
scale_color_manual(
values = colors,
drop = FALSE
) +
theme_bw()
# With limits
mtcars_tbl %>%
ggplot(aes(mpg, wt)) +
geom_point(aes(colour = cyl)) +
scale_color_manual(
values = colors,
drop = FALSE,
limits = c("4", "6", "8", "10")
) +
theme_bw()
# With limits and breaks
mtcars_tbl %>%
ggplot(aes(mpg, wt)) +
geom_point(aes(colour = cyl)) +
scale_color_manual(
values = colors,
drop = FALSE,
breaks = c("4", "6", "8", "10"),
limits = c("4", "6", "8", "10")
) +
theme_bw()
# With limits on force
mtcars_tbl %>%
ggplot(aes(mpg, wt)) +
geom_point(aes(colour = cyl)) +
scale_color_manual(
values = colors,
drop = FALSE,
limits = force
) +
theme_bw()
# With limits on identity
mtcars_tbl %>%
ggplot(aes(mpg, wt)) +
geom_point(aes(colour = cyl)) +
scale_color_manual(
values = colors,
drop = FALSE,
limits = identity
) +
theme_bw()
Created on 2024-07-11 with reprex v2.1.1
The only way to get what I am looking for is to add an empty row where the missing factors are mentioned, and plot waiting for them to be eliminated.
library(dplyr, warn.conflicts = FALSE)
library(ggplot2)
mtcars_tbl <- mtcars %>%
as_tibble() %>%
mutate(
cyl = factor(cyl,
levels = c("4", "6", "8", "10"))
)
mtcars_tbl %>%
tibble::add_case(
cyl = factor("10",
levels = c("4", "6", "8", "10"))
) %>%
ggplot(aes(mpg, wt)) +
geom_point(aes(colour = cyl)) +
scale_color_brewer(drop = FALSE, palette = "Dark2")
#> Warning: Removed 1 row containing missing values or values outside the scale range
#> (`geom_point()`).
Created on 2024-07-11 with reprex v2.1.1
However, I think it is not an ideal solution, since add_case()
or bind_rows()
may have limitations when you have tibbles with list or different data type.
packageVersion("ggplot2")
#> [1] '3.5.1'
Created on 2024-07-11 with reprex v2.1.1