wilkelab / ggridges

Ridgeline plots in ggplot2
https://wilkelab.org/ggridges
GNU General Public License v2.0
411 stars 31 forks source link

Feature request: Vary colour/fill along ridgeline #82

Open roaldarbol opened 1 year ago

roaldarbol commented 1 year ago

Hey Claus - thanks for some amazing work with ggridges!

I'm using geom_ridgeline, and would like to be able to colour the line by a variable (e.g. the same as height). Although it's possible to colour the fill/colour using geom_density_ridges_gradient, it doesn't seem to be possible in other cases, e.g. for a time series.

Here's a minimal example of what I'd like to be able to do:

lincoln_weather %>% 
  mutate(
         date = as_date(CST),
         day_n = mday(date)) %>% 
  filter(as_date(date) < as_date("2017-01-01")) %>% 
ggplot(aes(x = day_n, y = Month, height = `Mean Temperature [F]`, fill = `Mean Temperature [F]`)) +
  geom_ridgeline(scale = 0.05)
clauswilke commented 1 year ago

I'm not sure what exactly you're asking. There is geom_ridgeline_gradient(). Does that do what you want, or are you asking for something different?

roaldarbol commented 1 year ago

It does almost - works for fill, but not for colour. I was using colour myself, and just assumed they would both be implemented in a similar way. So I guess the request is really about supporting varying colour. Currently, it raises the error:

Caused by error in `draw_group()`:
! These aesthetics can not vary along a ridgeline: color, size, linetype

Then in addition, it might be worth changing the error message of geom_ridgeline. The current error suggests that it's universally impossible to vary aesthetics along ridgelines (! Aesthetics can not vary along a ridgeline). Might be better to point people in the direction, that you should instead use geom_ridgeline_gradient, e.g.

Caused by error in `draw_group()`:
! Aesthetics can not vary along `geom_ridgeline` - use `geom_ridgeline_gradient` instead
clauswilke commented 1 year ago

The limitation of which aesthetics can vary come from the R graphics device. There's little I can do. And I don't want to encourage people to use the gradient versions of the geoms because I'm uncomfortable with how the effect is achieved. It's a bad workaround.

If at some point the R graphics device can vary color and/or size along a line then we can consider this feature.

roaldarbol commented 1 year ago

That's of course up to you. I think it would be useful now that it is implemented anyways.

I'm not sure about whether it's not possible to vary colour along a line. This example works just fine:

lincoln_weather %>% 
  mutate(date = as_date(CST),
         day_n = mday(date)) %>% 
  filter(as_date(date) < as_date("2017-01-01")) %>% 
ggplot(aes(x = day_n, y = `Mean Temperature [F]`, colour = `Mean Temperature [F]`, group = Month)) +
  geom_line()

Is there an underlying limitation you're thinking of?

EDIT: Ah, because the Y axis is essentially categorical in the ridgelines? But I guess if height is implemented, it should still be possible in theory?

clauswilke commented 1 year ago

The code in your latest example doesn't run for me. Please use the reprex package to provide examples: https://reprex.tidyverse.org/articles/magic-reprex.html

roaldarbol commented 1 year ago

Ah, sorry, here you go:

library(ggridges)
library(lubridate)
#> Loading required package: timechange
#> 
#> Attaching package: 'lubridate'
#> The following objects are masked from 'package:base':
#> 
#>     date, intersect, setdiff, union
library(tidyverse)
lincoln_weather %>% 
  mutate(date = as_date(CST),
         day_n = mday(date)) %>% 
  filter(as_date(date) < as_date("2017-01-01")) %>% 
ggplot(aes(x = day_n, y = `Mean Temperature [F]`, colour = `Mean Temperature [F]`, group = Month)) +
  geom_line()

Created on 2023-01-09 with reprex v2.0.2

clauswilke commented 1 year ago

The thing is this may look fine if you're not looking carefully, but you're not actually getting continuous lines, you're getting individual line segments. This is both ugly and causes a headache for something like ggridges. I can't use the same rendering code I currently have and just change line color along the way.

Increasing the line thickness demonstrates this clearly.

library(tidyverse)
library(ggridges)
library(lubridate)

lincoln_weather %>% 
  mutate(date = as_date(CST),
         day_n = mday(date)) %>% 
  filter(as_date(date) < as_date("2017-01-01")) %>% 
  ggplot(aes(x = day_n, y = `Mean Temperature [F]`, colour = `Mean Temperature [F]`, group = Month)) +
  geom_line(linewidth = 5)

Created on 2023-01-09 with reprex v2.0.2

roaldarbol commented 1 year ago

Oh boy, I didn't know that! That's unfortunate, I guess I'll just have to find a way around it for now then... Do you know if changing this behaviour is on the core R teams radar? Or the Posit team?