---
title: "Color scales in R"
author: Andrew Siefert
format: 
  html:
    embed-resources: true
    toc: true
    code-fold: true
    code-tools: true
    fig-height: 4
    fig-width: 6
execute:
  warning: false
---


# A little color theory

Three components of color (HCL space):

```{r}
library(colorspace)

swatchplot(
  "Hue (type of color)" = hex(polarLUV(H = seq(0, 300, length.out = 10), C = 50, L = 70)),
  "Chroma (colorfulness)" = hex(polarLUV(H = 0, C = seq(0, 100, length.out = 10), L = 65)),
  "Luminance (brightness)"  = hex(polarLUV(H = 260, C = 25, L = seq(90, 10, length.out = 10)))
)
```

* Captures human perceptual axes well
* Perceptually uniform -- a unit step anywhere in HCL space produces a constant perceptual change in color

**colorspace** package lets you create and explore palettes based on trajectories in HCL space.


## Hue

* Type of color (red, blue, green, etc.)
* Not perceived as ordered
* Values go from 0 to 360 (color wheel)

```{r}
library(colorspace)

hue <- polarLUV(H = seq(0, 300, 75), C = 60, L = 65)
hue
hex(hue)
swatchplot(hex(hue))
text(x = seq(0.1, 1, 0.2), y = 0.05, labels = seq(0, 300, 75))
```

## Chroma

* Purity or colorfulness of the color
* Perceived as ordered
* Ranges from 0 (gray) to maximum that varies with hue and luminescence

```{r}
chroma <- polarLUV(H = 0, C = seq(0, 100, 25), L = 65) 
swatchplot(hex(chroma))
text(x = seq(0.1, 1, 0.2), y = 0.05, labels = seq(0, 100, 25))
```

## Luminance

* Brightness
* Perceived as ordered
* Ranges from 0 (black) to 100 (white)

```{r}
lum <- polarLUV(H = 260, C = 25, L = seq(90, 10, -20))
swatchplot(hex(lum))
text(x = seq(0.1, 1, 0.2), y = 0.05, labels = seq(90, 10, -20))
```


# Type of palettes

* **Qualitative**: categorical information
* **Sequential**: ordered/numerical information (high to low)
* **Diverging**: ordered/numeric information around a central neutral value


### Qualitative palettes

* Distinguishes categories by a sequence of hues while keeping chroma and luminance constant
* Best to use equidistant sequence of hues spanning the color wheel
* Use lighter colors (moderate chroma, high luminance) for shading areas (e.g., bar plots, maps)
* Use more flashy colors (high chroma) for points and lines

Qualitative palettes in **colorspace**:
```{r}
hcl_palettes(type = "qualitative", plot = T)
```

Create a palette using `qualitative_hcl()`: 
```{r}
my_qual <- qualitative_hcl(6, palette = "Set3")
my_qual

demoplot(my_qual)

# plot palette in HCL space
hclplot(my_qual)
```

## Sequential palettes

* Codes numeric values by sequence of increasing or decreasing luminance
* Without chroma (`c = 0`), corresponds to grayscale
* Use larger range of luminance if you are plotting more values
* Can also vary chroma and/or hue to better distinguish colors

```{r}
hcl_palettes("sequential (single-hue)", n = 7, plot = TRUE, nrow = 6)
hcl_palettes("sequential (multi-hue)", n = 7, plot = TRUE)
```

```{r}
seq9 <- sequential_hcl(10, palette = "Greens 3")
demoplot(seq9, "heatmap")
hclplot(seq9)
specplot(seq9, type = "o")
```

## Diverging palettes 

* Combination of two sequential palettes with different hues in the left and right "arms"
* Neutral central value has zero chroma
* Chroma and luminance trajectories are mirrored in the two arms

```{r}
hcl_palettes("diverging", n = 7, plot = TRUE, nrow = 10)
```

```{r}
div12 <- diverging_hcl(12, palette = "Blue-Red")
demoplot(div12)
hclplot(div12)
specplot(div12, type = "o")
```


# Using colorspace with ggplot2

Scales are named via the scheme: 

`scale_<aesthetic>_<datatype>_<colorscale>(palette = <Palette>)`

* `<aesthetic>` is the name of the aesthetic (`fill`, `color`, etc.)
* `<datatype>` is the type of variable plotted (`discrete` or `continuous`)
* `<colorscale>` sets the type of color scale used (`qualitative`, `sequential`, or `diverging`)
* `<Palette>` is the name of the palette (e.g., `"Dark 3", "Blue-Red"`)

```{r}
library(ggplot2)

ggplot(iris, aes(x = Sepal.Length, fill = Species)) + 
  geom_density(alpha = 0.6) + 
  scale_fill_discrete_qualitative(palette = "Dark 3")
```

# Color blindness

**colorblindr** package simulates how a color palette will look to people with common forms of color blindness. 

Make a figure using default ggplot color scale:
```{r}
df <- data.frame(x = c("a", "b", "c", "d"), y = c(3, 4, 1, 2))
bars <- ggplot(df, aes(x, y, fill = x)) + 
  geom_bar(stat = "identity") + 
  labs(x = NULL, y = NULL) +
  theme(legend.position = "none")
bars
```

Look at color-vision-deficiency simulations: 
```{r}
library(colorblindr)

cvd_grid(bars)
```

A discrete color scale that works better for people with color blindness is the Okabe Ito palette. 
```{r}
palette_OkabeIto
swatchplot(palette_OkabeIto)

bars2 <- bars + scale_fill_OkabeIto()
bars2

cvd_grid(bars2)
```

# Some useful palettes

## viridis

viridis color scales are designed to have good perceptual properties, work well for people with colorblindness, and print well in gray scale.

```{r}
library(viridis)

viridis(10)
swatchplot(
  "viridis" = viridis(10),
  "magma" = viridis(10, option = "magma"),
  "inferno" = viridis(10, option = "inferno"), 
  "cividis" = viridis(10, option = "cividis"), 
  "rocket" = viridis(10, option = "rocket"),
  "mako" = viridis(10, option = "mako")
)
```

The viridis scales are available in ggplot2 using using `scale_fill_viridis_d()` and `scale_fill_viridis_c()`.


Discrete viridis scale:
```{r}
bars + scale_fill_viridis_d()
```


Continuous viridis scale:
```{r}
erupt <- ggplot(faithfuld, aes(waiting, eruptions, fill = density)) +
  geom_raster()

erupt
erupt + scale_fill_viridis_c(option = "magma")
```

## ColorBrewer

ColorBrewer scales are designed to work well for maps, but are also good for other types of data. They are available in the **RColorBrewer** package: 

```{r, fig.height=10}
library(RColorBrewer)

display.brewer.all()
```

Most palettes are colorblind friendly.
```{r, fig.height=8}
display.brewer.all(colorblindFriendly = T)
```

You can construct a palette using `brewer.pal()`:
```{r}
brewer.pal(9, name = "PuBu")
display.brewer.pal(10, name = "PuBu")
```

ColorBrewer scales are also built into ggplot2: 

* `scale_color_brewer()` and `scale_fill_brewer()` for discrete scales
* `scale_color_distiller()` and `scale_fill_distiller()` for continuous scales

```{r}
bars + scale_fill_brewer(palette = "Set2")
```

```{r}
erupt + scale_fill_distiller(palette = "RdPu")
```

## scico

scico includes 39 palettes designed for scientific data visualization. They have good perceptual properties and are colorblind safe. 

```{r}
library(scico)

scico_palette_show()
scico(20, palette = "lapaz") |> swatchplot()
erupt + scale_fill_scico(palette = "davos")
```


# Paletteer

The **paletteer** package provides a unified interface to color scales from many packages.

```{r}
library(paletteer)

paletteer_d("nationalparkcolors::BryceCanyon", 5)
paletteer_c("scico::devon", 10)
bars + scale_fill_paletteer_d("wesanderson::FantasticFox1")
```

# Manual scales

You can set colors manually in ggplot2 using `scale_color_manual()` and `scale_fill_manual()`.

```{r}
bars + scale_fill_manual(values = c("forestgreen", "goldenrod", "firebrick", "cornflowerblue"))
```

Here are Erika's cheat sheets for ColorBrewer scales: 
![](image1.png)
![](image2.png)
![](image3.png)

```{r}
bars + scale_fill_manual(values = c("#7FC97F", "#BEAED4", "#FDC086", "#FFFF99"))
```
