henryjean
henryjean

Reputation: 102

How to add a gradient fill to a geom_density chart

I have a dataset where I'd like to plot the density of one column and add a gradient fill that is associated with another column.

For example, this code creates the following plot

library(datasets)
library(tidyverse)

df <- airquality

df %>% 
  group_by(Temp) %>% 
  mutate(count = n(), 
         avgWind = mean(Wind)) %>% 
  ggplot(aes(x = Temp, fill = avgWind)) + 
  geom_density()

plot example

What I'd like is for the plot to have a gradient fill that indicates what the average wind (avgWind) was at each temperature along the x-axis.

I've seen some examples that allow me to create a gradient fill that is associated with the values on the x-axis itself (in this case, Temp) or by percentile/quantiles, but I'd like the gradient fill to be associated with an additional variable.

It's sort of like this, but instead of a bar plot, I'd like to keep it as a smoothed density chart:

df %>% 
  group_by(Temp) %>% 
  mutate(count = n(), 
         avgWind = mean(Wind)) %>% 
  ggplot(aes(x = (Temp), fill = avgWind, group = Temp)) + 
  geom_bar(aes(y = (..count..)/sum(..count..)))

enter image description here

Upvotes: 1

Views: 1149

Answers (1)

alan ocallaghan
alan ocallaghan

Reputation: 3038

You can't do gradient fills in geom_polygon so the usual solution is to draw lots of line segments. For example you could do something like this:

library("datasets")
library("tidyverse")
library("viridis")


df <- airquality

df <- df %>%
  group_by(Temp) %>%
  mutate(count = n(), avgWind = mean(Wind))

## Since we (presumably) want continuous fill, we need to interpolate to
## get avgWind at each Temp value.
## The edges are grey because KDE is estimating density 
## Where we don't know the relationship between temp and avgWind
d2fun <- approxfun(df$Temp, df$avgWind)
#> Warning in regularize.values(x, y, ties, missing(ties)): collapsing to unique
#> 'x' values
dens <- density(df$Temp)

dens_df <- data.frame(x = dens$x, y = dens$y, fill = d2fun(dens[["x"]]))

ggplot(dens_df) +
  geom_segment(aes(x = x, xend = x, y = 0, yend = y, color = fill)) +
  scale_color_viridis()

Upvotes: 3

Related Questions