Gradient alpha centered around 0 in ggplot2?

Viewed 41

I would like to plot densities by groups such that the alpha value decreases (more transparent) as the x axis value gets closer to 0.

Based on the data dataset, I generate the alpha column by rescaling the x axis values around 0.

I thought that adding the alpha inside the aes() would work but this throws and error.

library(tidyverse)
library(purrr)
library(scales)

set.seed(123)
data <- tibble(A = rnorm(100),
               B = rnorm(100, mean = -0.7),
               C = rnorm(100, mean = 1)) %>% 
  pivot_longer(cols = everything(), 
               names_to = "model") %>% 
  group_by(model) %>% 
  summarise(value = list(value)) %>%
  mutate( xval = map(value, ~density(.x)$x),
          yval = map(value, ~density(.x)$y)) %>% 
  select(-value) %>% 
  unnest(ends_with("val"))

#create alpha column
df <- data %>% 
  group_by(model) %>% 
  mutate(myalpha = abs(scale(xval, center = 0)), #scale to center around 0
         myalpha2 = scales::rescale_mid(myalpha, mid = 0) #rescale 0-1, 0 for values around 0
         ) %>% 
  as_tibble() 

df %>% 
  ggplot(aes(x = xval, y = yval,
             fill = model, col = model))+
  geom_line()+
  geom_vline(xintercept = 0)+
  geom_density(aes(alpha = myalpha2), #alpha white around 0
               stat = "identity")+
  scale_fill_manual(values = c("red", "pink", "orange"))+
  scale_alpha_identity()
#> Error in `f()`:
#> ! Aesthetics can not vary with a ribbon

Created on 2022-09-11 by the reprex package (v2.0.1)

1 Answers

You cannot yet have a gradient fill in native ggplot (this includes gradients on the alpha channel). You can give the appearance of gradient fills using vertical line segments whose individual alpha values change along the x axis though.

Note that your alpha calculation isn't quite right here. myalpha2 has a minimum of 0.5 at the 0 point, as you can easily check with min(df$myalpha2).

To fix this, and implement the vertical line segment hack, you can do:

df %>% 
  mutate(myalpha2 = 2 * (as.vector(myalpha2) - 0.5)) %>%
  ggplot(aes(x = xval, y = yval))+
  geom_line()+
  geom_vline(xintercept = 0)+
  geom_segment(aes(alpha = myalpha2, xend = xval, yend = 0, color = model), 
               size = 1) +
  scale_color_manual(values = c("red", "pink", "orange"))+
  scale_alpha_identity()

enter image description here

Related