1

I am trying to add a line segment intervals to a ggplot. However, I am trying to make the line segments a gradient that fades the alpha to zero at each end of the interval.

For example, if I create a plot that includes some intervals, like so:

    library(ggplot2)
library(dplyr)

df <- data.frame(
  name = c('x1', 'x2', 'x3'),
  value = c(0.251, 0.207, 0.182),
  seg = c(0.027, 0.028, 0.049)
)

p <- df %>%
  ggplot() + aes(x=name, y=value) +
  geom_segment(aes(x=name, xend=name, y=(value - seg), yend=(value + seg),
                   col = name), 
               size = 5) +
  geom_point(aes(x=name, y = value), shape = 18, size = 5, color = "black") +
  theme_bw() +
  xlab('Name') +
  ylab("Value") 

p

This produces a plot like this: interval plot

However, I am trying to figure out a way to turn those line segments into a thicker bar, that fades the alpha to zero at each end.

Something like the plot below (which can be found here)... but Im not sure how to create this style of plot with my data. gradient interval

For clarity, I am just trying to recreate the coloured gradient intervals from the plot above.

EDIT

As per one of the comments, I tried using geom_link for this... but I cant seem to get it to work correctly.

To begin, I created a vector of alpha values to pass to geom_link like so:

alpLow <- seq(from = 0, to = 1, length.out = 150)
alpHigh <- rev(alpLow)
alp <- c(alpLow, alpHigh)

And then used this in geom_link:

p <- df %>%
  ggplot() + aes(x=name, y=value) +
  geom_link(aes(x = name, y = (value - seg),
                xend = name, yend = (value + seg), 
                colour = stat(index)), lineend = "round", size = 5, alpha = alp)

Which produces this: gradient seqment

As you can see, it only applies the gradient at the start and end of the 1st and last line segment.

Furthermore, Im not entirely pleased with the aesthetic of using geom_link as it seems to link together points (which are visible when you zoom in)... I was really hoping for a solid bar that fades the alpha.

Electrino
  • 2,636
  • 3
  • 18
  • 40
  • Does this answer your question? [R: is it possible to draw a geom\_segment line with a colour gradient? (or is there another way to emphasize start vs end?)](https://stackoverflow.com/questions/55752424/r-is-it-possible-to-draw-a-geom-segment-line-with-a-colour-gradient-or-is-the) – tjebo Dec 01 '21 at 11:58
  • I am guessing, the problem is we have a summary data, no enough data points to make a gradient? – zx8754 Dec 01 '21 at 12:03
  • I am guessing I should use some type of scale_alpha argument. But Im not sure what to use. But I will update my question to make it more clear – Electrino Dec 01 '21 at 12:22
  • Additionally, I don't feel my question is a duplicate, as in the link you provide @tjebo, they only provide a single value for the alpha. That is not what Im trying to achieve – Electrino Dec 01 '21 at 12:29
  • I cant seem to get it to work correctly using `geom_link`. I will update the question with some additional code using `geom_link` – Electrino Dec 01 '21 at 12:53

2 Answers2

1

Use ggforce::geom_link

alpha = stat(index) is just one option, from the documentation.

library(tidyverse)
library(ggforce)

df <- data.frame(
  name = c('x1', 'x2', 'x3'),
  value = c(0.251, 0.207, 0.182),
  seg = c(0.027, 0.028, 0.049)
)


df %>%
  ggplot(aes(x=name, y=value)) +
  geom_link(aes(x=name, xend=name, yend=value + seg,
                   col = name, alpha = rev(stat(index))), 
               size = 5) +
  geom_link(aes(x=name, xend=name, yend=value - seg,
                   col = name, alpha = rev(stat(index))), 
               size = 5) +
  
  geom_point(aes(x=name, y = value), shape = 18, size = 5, color = "black") +
  theme_bw() +
  labs(x= 'Name', y = "Value") 


enter image description here

tjebo
  • 21,977
  • 7
  • 58
  • 94
  • regarding that pointillistisc look - you can control the number of points with the n argument. – tjebo Dec 01 '21 at 13:32
1

I hope the below is sufficiently different to merit a new answer. I have had a bit more time to look into the link which you have provided. {ggdist} has those gradient interval stats - they need the underlying data and not summary data for calculation of their density.

Assuming that you have summarised data in a way that those values represent the distribution of your data (e.g., a normal distribution), you can use this in order to recreate data based on those values. I have here created normal distributions for each group, using your values as mean and standard deviation, and then you can use ggdist::stat_gradientinterval. But you can also create other distributions of course.

library(tidyverse)
library(ggdist)

df <- data.frame(
  name = c('x1', 'x2', 'x3'),
  value = c(0.251, 0.207, 0.182),
  seg = c(0.027, 0.028, 0.049)
)

df_norm <- 
df %>%
  split(., .$name) %>%
  map(function(x) rnorm(100, x$value, x$seg)) %>%
  bind_rows() %>%
  pivot_longer(everything(), names_to = "name", values_to = "value")
  
ggplot(df_norm, aes(x=name, y=value, fill= name)) +
  ggdist::stat_gradientinterval() +
  theme_bw() +
  labs(x= 'Name', y = "Value") 

Created on 2021-12-01 by the reprex package (v2.0.1)

tjebo
  • 21,977
  • 7
  • 58
  • 94