1

I have a dataset myData which contains x and y values for various Samples. I can create a line plot for a dataset which contains a few Samples with the following pseudocode, and it is a good way to represent this data:

myData <- data.frame(x = 290:450, X52241 = c(..., ..., ...), X75123 = c(..., ..., ...))
myData <- myData %>% gather(Sample, y, -x)
ggplot(myData, aes(x, y)) + geom_line(aes(color=Sample))

Which generates:

Line plot of absorbance data

This turns into a Spaghetti Plot when I have a lot more Samples added, which makes the information hard to understand, so I want to represent the "hills" of each sample in another way. Preferably, I would like to represent the data as a series of stacked bars, one for each myData$Sample, with transparency inversely related to what is in myData$y. I've tried to represent that data in photoshop (badly) here:

What I would like to make

Is there a way to do this? Creating faceted plots using facet_wrap() or facet_grid() doesn't give me what I want (far too many Samples). I would also be open to stacked ridgeline plots using ggridges, but I am not understanding how I would be able to convert absolute values to a stat(density) value needed to plot those.

Any suggestions?

chemdork123
  • 12,369
  • 2
  • 16
  • 32
  • 2
    Can you post a minimal dataset? Generally, you can change the transparency based on values in a variable by adding `alpha = *your column name*` inside the `aes()` section – Joris Mar 17 '20 at 17:58
  • Oh wow! Yes, the answer is through an alpha aesthetic! I got something to work by running essentially: `ggplot(myData, aes(Sample, x)) + geom_col(aes(alpha=y)) + coord_flip()`. – chemdork123 Mar 17 '20 at 18:14
  • Great, glad it worked! – Joris Mar 17 '20 at 18:15
  • For some more info, I was able to get exactly what I needed by switching to `geom_segment()` and applying the aesthetic over alpha. Key with this approach is to realize that I had to avoid the function from "drawing over" other segments by splitting into individual segments with delta-x = 1. Here the pseudocode is something like: `p + geom_segment(aes(x=x, xend=x-1, y=Sample, yend=Sample, alpha=y), size=8)`. Worked like a charm. Even better, I could add `alpha=ifelse(y > num, 1, 0)` to make "hard-edged" rectangles instead of the gradient, with the edges = `num`. – chemdork123 Mar 18 '20 at 15:34

1 Answers1

0

Thanks to u/Joris for the helpful suggestion! Since, I did not find this question elsewhere, I'll go ahead and post the pretty simple solution to my question here for others to find.

Basically, I needed to apply the alpha aesthetic via aes(alpha=y, ...). In theory, I could apply this over any geom. I tried geom_col(), which worked, but the best solution was to use geom_segment(), since all my "bars" were going to be the same length. Also note that I had to "slice" up the segments in order to avoid the problem of overplotting similar to those found here, here, and here.

ggplot(myData, aes(x, Sample)) +
  geom_segment(aes(x=x, xend=x-1, y=Sample, yend=Sample, alpha=y), color='blue3', size=14)

That gives us the nice gradient:

enter image description here

Since the max y values are not the same for both lines, if I wanted to "match" the intensity I normalized the data (myDataNorm) and could make the same plot. In my particular case, I kind of preferred bars that did not have a gradient, but which showed a hard edge for the maximum values of y. Here was one solution:

ggplot(myDataNorm, aes(x, Sample)) +
  geom_segment(aes(x=x, xend=x-1, y=Sample, y=end=Sample, alpha=ifelse(y>0.9,1,0)) +
  theme(legend.position='none')

enter image description here

Better, but I did not like the faint-colored areas that were left. The final code is what gave me something that perfectly captured what I was looking for. I simply moved the ifelse() statement to apply to the x aesthetic, so the parts of the segment drawn were only those with high enough y values. Note my data "starts" at x=290 here. Probably more elegant ways to combine those x and xend terms, but whatever:

ggplot(myDataNorm, aes(x, Sample)) +
  geom_segment(aes(
    x=ifelse(y>0.9,x,290), xend=ifelse(y>0.9,x-1,290),
    y=Sample, yend=Sample), color='blue3', size=14) +
  xlim(290,400)  # needed to show entire scale

enter image description here

chemdork123
  • 12,369
  • 2
  • 16
  • 32