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.

5
  • 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?) Commented Dec 1, 2021 at 11:58
  • I am guessing, the problem is we have a summary data, no enough data points to make a gradient? Commented Dec 1, 2021 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 Commented Dec 1, 2021 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 Commented Dec 1, 2021 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 Commented Dec 1, 2021 at 12:53

2 Answers 2

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)

Sign up to request clarification or add additional context in comments.

Comments

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

1 Comment

regarding that pointillistisc look - you can control the number of points with the n argument.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.