Reputation: 355
I have two data set with a different range of y values, the y range of one data set includes the other. I'm trying to make separate plots for each data set, but combine the two legends, while keeping the color scheme separate.
I'm using iris
dataset below, and created iris2
as an example of the larger dataset.
iris2 <- iris
iris2$Sepal.Length <- iris$Sepal.Length*10
iris2 <- rbind(iris, iris2)
Then I plotted iris
and iris2
separately like below.
g1 <- ggplot(iris, aes(x=Petal.Length, y=Petal.Width, fill=Sepal.Length)) +
geom_point(size=5, shape=21) +
scale_color_gradient(low="white",high="red", aesthetics="fill")
g2 <- ggplot(iris2, aes(x=Petal.Length, y=Petal.Width, fill=Sepal.Length)) +
geom_point(size=5, shape=21) +
scale_color_gradient(low="red",high="blue", aesthetics="fill")
What I'd like to do is to keep the color scheme for g1
, so that if I create a new legend for g2
, the legend will still show white
as 0
and red
as 8
, then from red
at 8
start changing colors until it becomes blue
at 80
. (So that I can ultimately just keep the legend for g2
, as it would show color schemes for both g1
and g2
data)
I tried to do this by using scale_color_manual
like below but can't use it because this is forcing discrete values into a continuous scale.
scale_color_manual(c(0,max(iris$Sepal.Length),max(iris2$Sepal.Length)), values = c("white", "red", "blue"), aesthetics = "fill")
I also considered changing fill=Sepal.Length
to fill=as.factor(Sepal.Length)
to deal with that problem, but that would require me to manually type in dozens of colors to be used. Any advice?
(Just a note: in this reproducible example, iris2
includes the same Sepal.Length
values as iris
so there would be no need to actually produce g1
, but y values from my actual dataset do not overlap. That was just for me to create a quick reproducible example)
Upvotes: 1
Views: 431
Reputation: 36076
You could bind your datasets and use facets with scale_fill_gradientn()
to make the color scale with the correct midpoint at the max of the first dataset (only relevant if you want a continuous color bar).
This approach involves using scales::rescale()
, which is mentioned in the documentation for the values
argument of scale_fill_gradientn()
.
That could look something like:
iris2 = iris
iris2$Sepal.Length = iris$Sepal.Length*10
iris2 = rbind(iris, iris2)
iris$name = "iris"
iris2$name = "iris2"
iris3 = rbind(iris, iris2)
library(ggplot2)
ggplot(iris3, aes(x = Petal.Length, y = Petal.Width, fill = Sepal.Length) ) +
geom_point(size = 5, shape = 21) +
scale_fill_gradientn(colors = c("white", "red", "blue"),
values = scales::rescale(c(min(iris$Sepal.Length),
max(iris$Sepal.Length),
max(iris2$Sepal.Length))) ) +
facet_wrap(~name) +
theme(strip.background = element_blank(),
strip.text = element_blank() )
You can change the breaks
of the scale to make things more clear, as needed.
Even if you don't want to use facets, you could make a plot of the combined data and create the legend with scale_fill_gradientn()
to use with your other plots. One nice way to extract legends and combine plots and legends is with package cowplot. See cowplot::get_legend()
.
For the legend size
You can increase the physical hight of the legend via legend.key.height
in theme()
.
ggplot(iris3, aes(x = Petal.Length, y = Petal.Width, fill = Sepal.Length) ) +
geom_point(size = 5, shape = 21) +
scale_fill_gradientn(colors = c("white", "red", "blue"),
values = scales::rescale(c(min(iris$Sepal.Length),
max(iris$Sepal.Length),
max(iris2$Sepal.Length))) ) +
facet_wrap(~name) +
theme(strip.background = element_blank(),
strip.text = element_blank(),
legend.key.height = unit(1.5, "cm"))
If you don't have any 0 values you could also try working with the legend on the log scale, which can be done with trans
in scale_fill_gradientn()
, but it might take some fiddling to get things to look right.
Upvotes: 2