2

I would like to create a geom_line, or possibly geom_ribbon or geom_area, with a "fading-out" effect below the line similar to that used in the Thomson Reuters Eikon terminal.

I've tried a very simple approach based on geom_ribbon, setting alpha based on the y value, with an idea that I could normalise it based on a based value, but received this error: Error in f(...) : Aesthetics can not vary with a ribbon

(Non-working) code example:

library( tidyverse )
library( ggplot2 )

x <- seq( 0, 99 )
y <- rnorm( 100 ) + 4

tib <- tibble( x, y )

gp <- ggplot( tib ) +
  geom_ribbon( aes( x=x, ymax=y, ymin=y-1, alpha=y) ) +
  geom_line( aes( x=x, y=y ) )

I would like the output to resemble the first plot in this blog post (ironically about ggplot2's geom_line): A Detailed Guide to Plotting Line Graphs:

enter image description here

Or, as mentioned, the output of the Thomson Reuters Eikon terminal shown in the top of the two plots in the second image on this page: Thomson Reuters Eikon Review:

enter image description here

tealeaf
  • 41
  • 6
  • See [How to make gradient color filled timeseries plot in R](https://stackoverflow.com/questions/27250542/how-to-make-gradient-color-filled-timeseries-plot-in-r) and "Linked" therein. – Henrik Apr 19 '19 at 15:57
  • @Henrik Ah, that's definitely the right question, although focused on colour gradients rather than alpha, but there doesn't seem to be a good ggplot-based answer there in any case. I'll hold out to see if anyone else answers this specific one. (The answer is also over four years old, and there have been quite a few developments in ggplot2 since then.) Thanks for pointing it out, though! – tealeaf Apr 19 '19 at 16:14

2 Answers2

1

Almost four years later, a few changes in R's graphics engine, and a very helpful package have provided a neat and usable solution to this.

The library I'm using is ggpattern: https://coolbutuseless.github.io/package/ggpattern/

By using a geom_area_pattern with a gradient fill and an alpha channel in the colour specification for pattern_fill and pattern_fill2, I can get a reasonably close approximation to the original Thomson Reuters Eikon terminal-style graph shown in my original question.

library( tidyverse )
library( ggplot2 )
library( ggpattern )

plot_data <-
    economics %>%
    select( date, uempmed )

gp <- 
    ggplot( plot_data ) +
    geom_area_pattern(  aes( x=date, y=uempmed ), 
                        colour          = '#ff7518cc',
                        pattern         = 'gradient',
                        fill            = NA, 
                        pattern_fill    = "#ff751800",
                        pattern_fill2   = "#ff751866" ) +
    theme(  panel.background = element_rect(fill = "#222222", colour = "#222222"), 
            plot.background = element_rect(fill = "#222222", colour = "#222222"), 
            axis.title.y = element_text( angle=90 ) )

print( gp )

Line graph with vertical fading transparency beneath the line.

tealeaf
  • 41
  • 6
0

Here's a quick cheat. It won't look great if you require more than one overlapping line, but I don't think that should be the use case anyway. Adding unnecessary fading alpha to a plot comes rather close to chartjunk, & if multiple lines need to be compared in the same chart, I recommend avoiding such embellishments for a cleaner, less distracting look.

ggplot(tib) +

  # rectangular gradient layer as background
  annotation_raster(raster = c("blue",      # top colour
                               "white") %>% # bottom colour
                      alpha(0.5),           # alpha
                    xmin = min(tib$x), xmax = max(tib$x),
                    ymin = 0, ymax = max(tib$y),
                    interpolate = TRUE) +

  # whiteout layer (replace white with relevant panel.background's
  # fill value, if a non-white background theme is used)
  geom_ribbon(aes(x = x, ymin = y, ymax = Inf), 
              fill = "white") +

  # actual line
  geom_line(aes(x = x, y = y), 
            color = "blue", size = 1) +
  theme_classic()

plot

Data:

set.seed(4321)
x <- seq(0, 99)
y <- rnorm(100) + 4

tib <- tibble(x, y)
Z.Lin
  • 28,055
  • 6
  • 54
  • 94
  • I agree that it's dangerously close to unnecessary, but I was also thinking about this as a potential tool for expressing credible intervals and similar. This felt like a good base case. For now, this is the neatest ggplot2-based approach I've seen, and certainly worth a play. Thank you! – tealeaf Apr 20 '19 at 20:28
  • One limitation is that the alpha blending is "global" over the whole chart, and doesn't descend from the line, but it's definitely a clever approach and, in a way, highlights that this really isn't something easily achievable in ggplot2. (Probably with good reason.) – tealeaf Apr 20 '19 at 20:31