1

First of all, some data similar to what I am working with.

rawdata <- data.frame(Score = rnorm(1000, seq(1, 0, length.out = 10), sd = 1),
                      Group = rep(LETTERS[1:3], 10000))
rawdata$Score <- ifelse(rawdata$Group == "A", rawdata$Score+2,rawdata$Score) 
rawdata$Score <- ifelse(rawdata$Group == "C", rawdata$Score-2,rawdata$Score)

stdev <- c(10.78,10.51,9.42)
col <- c("#004d8d", "#cc2701", "#e5b400") 

Now, the code of my geom_density_ridges with quantile lines, which in this case they will be white.

p <- ggplot(rawdata, aes(x = Score, y = Group)) +
     scale_y_discrete() +
     geom_rect(inherit.aes = FALSE, mapping = aes(ymin = 0, ymax = Inf, xmin = -0.1 * min(stdev), xmax = 0.1 * max(stdev)), 
               fill = "grey", alpha = 0.5) +
     geom_density_ridges(scale = -0.5, size = 1, alpha=0.5, show.legend = FALSE,
               quantile_lines = TRUE, quantiles = c(0.025, 0.975), 
               vline_color = "white", aes(fill = Group)) +
     scale_color_manual(values = col) +   
     scale_fill_manual(values = col) +
     labs(title="Toy Graph", y="Group", x="Value") +
     coord_flip(xlim = c(-8, 8), ylim = NULL, expand = TRUE, clip = "on")

p

An we obtain the following plot, which is perfectly adjusted to expectation.

enter image description here

Now I was wondering if there was a way to make only this little white quantile line transparent to the background. I tried first to set the vline_color = "transparent" and leaving the aes(fill = Group) at the end of geom_density_ridges at the logic that options where drew in order but it gets transparent not to the different shades of grey background but to the density fill (so the quantile line disappears), which is not what I am trying to achieve.

Thanks in advance for your ideas!

Unai Vicente
  • 367
  • 3
  • 10
  • Thanks for the response. This is not what I was looking for though. However, if there is definitely no other possible options I will opt for this. – Unai Vicente Nov 14 '22 at 16:38
  • Hi Unai. It's somewhat unclear what you want to achieve - Are you happy with the transparent fill? Do you want the quantile lines in the same color as the fill but transparent? – tjebo Nov 14 '22 at 17:01
  • 1
    Nailed it in the answer. – Unai Vicente Nov 14 '22 at 17:14

3 Answers3

2

Colors can be modified with scales::alpha. This can be passed to your color argument.

library(ggridges)
library(ggplot2)
rawdata <- data.frame(Score = rnorm(1000, seq(1, 0, length.out = 10), sd = 1),
                      Group = rep(LETTERS[1:3], 10000))
rawdata$Score <- ifelse(rawdata$Group == "A", rawdata$Score+2,rawdata$Score) 
rawdata$Score <- ifelse(rawdata$Group == "C", rawdata$Score-2,rawdata$Score)

stdev <- c(10.78,10.51,9.42)
col <- c("#004d8d", "#cc2701", "#e5b400") 
ggplot(rawdata, aes(x = Score, y = Group)) +
  scale_y_discrete() +
  geom_rect(inherit.aes = FALSE, mapping = aes(ymin = 0, ymax = Inf, xmin = -0.1 * min(stdev), xmax = 0.1 * max(stdev)), 
            fill = "grey", alpha = 0.5) +
  geom_density_ridges(scale = -0.5, size = 1, alpha=0.5, show.legend = FALSE,
                      quantile_lines = TRUE, quantiles = c(0.025, 0.975), 
### The only change is here
                      vline_color = alpha("white", .5), aes(fill = Group)) +
  scale_color_manual(values = col) +   
  scale_fill_manual(values = col) +
  labs(title="Toy Graph", y="Group", x="Value") +
  coord_flip(xlim = c(-8, 8), ylim = NULL, expand = TRUE, clip = "on")
#> Picking joint bandwidth of 0.148
#> Warning: Using the `size` aesthietic with geom_segment was deprecated in ggplot2 3.4.0.
#> ℹ Please use the `linewidth` aesthetic instead.

Created on 2022-11-14 with reprex v2.0.2

tjebo
  • 21,977
  • 7
  • 58
  • 94
  • 1
    It turns out this was exactly what I was asking for. I wanted to know how to pass an alpha to a colour and I didn't know this option existed. Thank you!. – Unai Vicente Nov 14 '22 at 17:11
  • 1
    It's a nice answer and obviously fits what the OP was looking for, but I don't think this literally leaves transparent strips in the density curve. – Allan Cameron Nov 14 '22 at 17:18
1

No, if you make something transparent you will see what's underneath, which is the density plot.
However, you can replicate the visual effect of "seeing through to the background" by simply setting the line colour to the same as the background.

Your grey rectangle is currently plotted underneath the density plots, therefore the "background" doesn't have a single colour. This can be solved by plotting it on top instead. Instead of a 50% grey with 50% alpha, you can replicate the same effect with a 0% grey (aka black) with a 25% alpha. Move the geom_rect later than the density plots and it will be layered on top.

Finally, your geom_rect is being called once for each row of raw_data, since it inherits the same data as the main plot. You probably don't want that, so specify a (dummy) data source instead.

ggplot(rawdata, aes(x = Score, y = Group)) +
  scale_y_discrete() +
  geom_density_ridges(scale = -0.5, size = 1, alpha=0.5, show.legend = FALSE,
                      quantile_lines = TRUE, quantiles = c(0.025, 0.975), 
                      vline_color = "grey90", aes(fill = Group)) +
  scale_color_manual(values = col) +   
  scale_fill_manual(values = col) +
  labs(title="Toy Graph", y="Group", x="Value") +
  geom_rect(data=data.frame(), inherit.aes = FALSE, mapping = aes(
      ymin = 0, ymax = Inf, xmin = -0.1 * min(stdev), xmax = 0.1 * max(stdev)
    ), fill = "black", alpha = 0.25) +
  coord_flip(xlim = c(-8, 8), ylim = NULL, expand = TRUE, clip = "on")

enter image description here

Note: I'm not sure the background colour is really "grey90", I've eyeballed it. You may want to specify it explicitly with theme if you want to be exact.

Ottie
  • 1,000
  • 3
  • 9
1

If you want literal see-through portions of your density curves, you will need to make the gaps yourself:

library(tidyverse) 

rawdata %>%
  mutate(GroupNum = as.numeric(as.factor(Group))) %>%
  group_by(GroupNum, Group) %>%
  summarise(yval = first(GroupNum) - density(Score)$y,
            xval = density(Score)$x,
            q025 = quantile(Score, 0.025),
            q975 = quantile(Score, 0.975)) %>%
  mutate(Q = ifelse(xval < q025, 'low', ifelse(xval > q975, 'hi', 'mid'))) %>%
  ggplot(aes(xval, yval, group = interaction(Group, Q))) +
  geom_line(size = 1) +
  geom_ribbon(aes(ymax = GroupNum, ymin = yval, fill = Group),
                  color = NA, alpha = 0.5, outline.type = 'full',
              data = . %>% filter(abs(q025 - xval) > 0.03 & 
                                    abs(q975 - xval) > 0.03)) +
  coord_flip() +
  scale_fill_manual(values = col) +
  scale_y_continuous(breaks = 1:3, labels = levels(factor(rawdata$Group)),
                     name = 'Group') +
  labs(x = 'Score')

enter image description here

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87