-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Description
I found a problem with scale_color_gradient2(). When I give it a low/high argument, it doesn't seem to map the low/high value of my data to the given color, but does something similar to shifting the color palette, to match the midpoint.
I expected the color specified to low/high argument to map the lowest/highest values in my data. I expected this, because in the documentation (https://ggplot2.tidyverse.org/reference/scale_gradient.html), about the arguments low/high, it says: "Colours for low and high ends of the gradient." which I believe indicates what I expect. If its just trimming the gradient range, then how is it different from limits argument?
Here is the code to reproduce the bug:
# load libraries
library(tidyverse)
library(patchwork)
library(scales)
#>
#> Attaching package: 'scales'
#> The following object is masked from 'package:purrr':
#>
#> discard
#> The following object is masked from 'package:readr':
#>
#> col_factor
iris <- iris %>% as_tibble()
iris$Sepal.Length2 <- iris$Sepal.Length - 5.5 # just so that we have negative and positive values, which demonstrates the bug better
# now the range of iris$Sepal.Length2 is c(-1.2, 2.4)
# gather the min and max values as they will be handy below
min_val = iris$Sepal.Length2 %>% min()
max_val = iris$Sepal.Length2 %>% max()
# lets just take the datapoints with the minimum and maximum for Sepal.Length2 so that there is no confusion about averaging of
# values to make the plot
iris_subset <- iris %>% filter(Sepal.Length2 %in% c(min_val, max_val))
# first plot, using scale_color_gradient2, which should have mapped the lowest value, -1.2 to steelblue, but looking at the plot
# it is clear that that is not the case
p1 <- ggplot(iris_subset, aes(x = Species, y = 0, color = Sepal.Length2)) +
geom_point(size = 10) +
theme_minimal() +
scale_color_gradient2(low = 'steelblue', mid = 'white', high = 'darkred', midpoint = 0)
# make a second plot which does exactly what I had expected scale_color_gradient2 would do. Here, I use scale_color_gradientn, and
# manually scale the values between 0 and 1, and specify the colors.
p2 <- ggplot(iris_subset, aes(x = Species, y = 0, color = Sepal.Length2)) +
geom_point(size = 10) +
theme_minimal() +
scale_color_gradientn(colors = c('steelblue', 'white', 'darkred'), values = scales::rescale(c(min_val, 0, max_val), to = c(0,1)))
patchwork::wrap_plots(p1, p2, ncol = 1)
# we can see from the left point (setosa) that the color in the first plot is fainter, which means that the mapping of lowest value
# to the color supplied to low argument hasn't been done appropriatelyCreated on 2025-11-03 with reprex v2.1.1
Thanks a lot!
