Reputation: 1525
Say if have the following plot.
library(ggplot2)
n <- 1169
df22 <- data.frame(x = 1:n, val = seq(0, 0.5, length.out = n), type = 1)
ggplot(df22, aes(x = x, y = val)) +
geom_ribbon(aes(ymax = val, ymin = 0, fill = type, group = type))
Instead of the blue color i would like to have a Gradient fill (from blue to red - vertically. So starting with blue at the bottom and red on top with a Parameter to Control the smoothness of Color change).
I found the following resource: https://ggplot2.tidyverse.org/reference/scale_gradient.html
Unfortunately, it didnt work out for me as my data is not continous(?).
Upvotes: 7
Views: 8100
Reputation: 124013
Using ggplot2 >= 3.5.0
(and R >= 4.2.0
) which adds support for gradient fills this can now more easily be achieved.
As a first step this requires to sepeify a gradient fill using e.g. grid::linearGradient
where the direction of the gradient can be set via the x1
, x2
, y1
and y2
argument, e.g. in your case we have to deviate from the defaults by setting x2 = unit(0, "npc")
to get a gradient in the vertical direction.
This gradient could then be applied to the geom
by passing it to the fill=
argument:
library(ggplot2)
library(grid)
grad_ungroup <- linearGradient(
c("blue", "red"),
x1 = unit(0, "npc"), y1 = unit(0, "npc"),
x2 = unit(0, "npc"), y2 = unit(1, "npc")
)
ggplot(df22, aes(x = x)) +
geom_ribbon(aes(ymax = val, ymin = 0),
fill = grad_ungroup
)
Upvotes: 2
Reputation: 5240
The following code will do it (but horizontally):
library(scales) # for muted
ggplot(df22, aes(x = x, y = val)) +
geom_ribbon(aes(ymax = val, ymin = 0, group = type)) +
geom_col(aes(fill = val)) +
scale_fill_gradient2(position="bottom" , low = "blue", mid = muted("blue"), high = "red",
midpoint = median(df22$val))
If you want to make it vertically, you may flip the coordinates using coord_flip()
upside down.
ggplot(df22, aes(x = val, y = x)) +
geom_ribbon(aes(ymax = val, ymin = 0)) +
coord_flip() +
geom_col(aes(fill = val)) +
scale_fill_gradient2(position="bottom" , low = "blue", mid = muted("blue"), high = "red",
midpoint = median(df22$val))
Or, if you want it to be horizontal with a vertical gradient (as you requested), you might need to go around it by playing with your data and using the geom_segment()
instead of geom_ribbon()
, like the following:
vals <- lapply(df22$val, function(y) seq(0, y, by = 0.001))
y <- unlist(vals)
mid <- rep(df22$x, lengths(vals))
d2 <- data.frame(x = mid - 1, xend = mid + 1, y = y, yend = y)
ggplot(data = d2, aes(x = x, xend = xend, y = y, yend = yend, color = y)) +
geom_segment(size = 1) +
scale_color_gradient2(low = "blue", mid = muted("blue"), high = "red", midpoint = median(d2$y))
This will give you the following:
Hope you find it helpful.
Upvotes: 11