1
votes

I'm trying to draw a plot that colors on two variables (a factor and an intensity). I would like each factor to be a different color, and I want the intensity to be a gradient between white and that color.

So far I've used techniques like facetting on the factor, setting color to be the interaction between the two variables, and setting color to the factor and alpha to intensity to approximate what I would like. However, I still feel like a gradient between white and the full color on one plot would represent this best.

Does anyone know how to do this without custom creating all of the color gradients and just setting them? In addition, is there a way to do it such that the legend works as if the graph was using color and alpha versus listing all of the colors as it does when setting color to the interaction?

So far I've tried:

ggplot(diamonds, aes(carat, price, color=color, alpha=cut)) +
  geom_point()

ggplot(diamonds, aes(carat, price, color=interaction(color, cut))) +
  geom_point()

ggplot(diamonds, aes(carat, price, color=color)) +
  geom_point() +
  facet_wrap(~cut)

What I'm trying to achieve is something that looks most like the graph using alpha, but instead of transparency, I would like a gradient between white and that color. In addition, I would like the legend to look like the one using color and alpha rather than the legend from for example the interaction plot.

1
I'd go with the facet_wrap option and look at one of the scale_color_gradient* functions to get the desired color gradient. The same aesthetic for more than one variable is something that just doesn't work well in ggplot. - neilfws

1 Answers

2
votes

The approach I usually use is to manipulate the factor values so I can plug them into the hcl() function.

First, some raw data:

library(tidyverse)

raw_data <-
  diamonds %>% 
  filter(price < 500, color %in% c("E", "F", "G")) %>% 
  mutate(
    factor = factor(color),
    intensity = cut,
    interaction = paste(factor, intensity)
  )

Next use this kind of wrangling to get hex colors:

color_values <-
  raw_data %>%
  distinct(factor, intensity, interaction) %>%
  arrange(factor, intensity) %>%
  mutate(
    interaction = fct_inorder(interaction),
    # get integer position of factors
    factor_int = as.integer(factor) - 1,
    intensity_int = as.integer(intensity),
    # create equal intervals for color, adding in some padding so we avoid extremes of 0, 1
    hue_base = factor_int / (max(factor_int) + 0.5),
    light_base = 1 - (intensity_int / (max(intensity_int) + 2)),
    # using ^^^ to feed into hcl()
    hue = floor(hue_base * 360),
    light = floor(light_base * 100),
    # final colors
    hex = hcl(h = hue, l = light)
  )

color_values %>% filter(intensity == "Good")
#  factor intensity interaction factor_int intensity_int hue_base light_base   hue light hex    
#  <ord>  <ord>     <fct>            <dbl>         <int>    <dbl>      <dbl> <dbl> <dbl> <chr>  
# E      Good      E Good               0             2      0        0.714     0    71 #D89FA9
# F      Good      F Good               1             2      0.4      0.714   144    71 #81BA98
# G      Good      G Good               2             2      0.8      0.714   288    71 #BDA4D2

Plot it:

ggplot(df, aes(x, y, color = interaction)) +
  geom_count() +
  facet_wrap(~factor) +
  scale_color_manual(
    values = color_values$hex,
    labels = color_values$interaction
  ) +
  guides(color = guide_legend(override.aes = list(size = 5)))

enter image description here