Skip to content

Use XKCD's Painbow colormap with ggplot

License

Unknown, MIT licenses found

Licenses found

Unknown
LICENSE
MIT
LICENSE.md
Notifications You must be signed in to change notification settings

steveharoz/painbow

Repository files navigation

Painbow

Painbow lets you use XKCD’s “painbow” colormap in ggplot.

XKCD implied that this colormap is terrible, and even called it a “painbow”. However, these examples show that with certain tasks and data, this colormap outperforms even some of the most commonly cited “good” colormaps like viridis.

XKCD's original:

A reproduction in with ggplot and the Painbow package using some custom theming:

Installation

To install the current release version, run:

install.packages("painbow")

Or you can install the latest development version:

install.packages("devtools")
devtools::install_github("steveharoz/painbow")

Examples

Setup:

library(tidyverse)
library(painbow)
library(patchwork) # combine multiple graphs

A simple example for the scale:

ggplot(faithfuld) +
  aes(waiting, eruptions, fill = density) +
  geom_raster(interpolate = TRUE) +
  scale_fill_painbow() +
  labs(title = "Can you find the most dense region?") +
  theme_bw(18)

The dataset from the comic

The dataset is painbow_data. It was made using the comic’s image and a scripted lookup table.

Painbow may help you find outliers

Here is a 2D field with a regular pattern and a deviation. Can you find it? Painbow makes a task easier compared with commonly touted “good” colormaps.

##### 2D #####

COUNT = 512

data = expand.grid(
  x = 1:COUNT,
  y = 1:COUNT) %>% 
  mutate(z = sin(x/16) + cos(y/16)) %>% 
  mutate(znoise = z + dnorm(sqrt((x-0.75*COUNT)^2 + (y-0.33*COUNT)^2)/COUNT*20))

ggplot(data) +
  aes(x=x, y=y, fill=znoise) + 
  geom_raster() +
  labs(title = "ggplot default", fill=NULL) + 
  theme_void(15) + theme(legend.text = element_blank()) +
ggplot(data) +
  aes(x=x, y=y, fill=znoise) + 
  geom_raster() +
  scale_fill_viridis_c() +
  labs(title = "Viridis", fill=NULL) + 
  theme_void(15) + theme(legend.text = element_blank()) +
ggplot(data) +
  aes(x=x, y=y, fill=znoise) + 
  geom_raster() +
  scale_fill_painbow() +
  labs(title = "XKCD's colormap", fill=NULL) + 
  theme_void(15) + theme(legend.text = element_blank()) +
patchwork::plot_annotation(
  title = "Three colormaps. Same data. Can you spot the weird region?", 
  theme = theme(text = element_text(size=20)))

Painbow can help you spot a subtle pattern among data with high dynamic range

######## 1D #########

COUNT = 1024

data = tibble(
  x = 1:COUNT,
  y = x/COUNT + sin(x/4)/100
)

ggplot(data) +
  aes(x = x, y=x) + 
  geom_line() +
  labs(title = "y = x") + 
  theme_void(15) + theme(legend.text = element_blank()) +
ggplot(data) +
  aes(x = x, y=COUNT/2, fill=x) + 
  geom_tile(width=1, height=COUNT, color=NA) +
  labs(title = "ggplot default") + 
  theme_void(15) + theme(legend.text = element_blank()) +
ggplot(data) +
  aes(x = x, y=COUNT/2, fill=x) + 
  geom_tile(width=1, height=COUNT, color=NA) +
  scale_fill_viridis_c() +
  labs(title = "viridis") + 
  theme_void(15) + theme(legend.text = element_blank()) +
ggplot(data) +
  aes(x = x, y=COUNT/2, fill=x) + 
  geom_tile(width=1, height=COUNT, color=NA) +
  scale_fill_painbow() +
  labs(title = "painbow") + 
  theme_void(15) + theme(legend.text = element_blank()) +

ggplot(data) +
  aes(x = x, y=y) + 
  geom_line() +
  labs(title = "y = x + sine wave") +
  theme_void(15) + theme(legend.text = element_blank()) +
ggplot(data) +
  aes(x = x, y=COUNT/2, fill=y) + 
  geom_tile(width=1, height=COUNT, color=NA) +
  labs(title = "ggplot default") + 
  theme_void(15) + theme(legend.text = element_blank()) +
ggplot(data) +
  aes(x = x, y=COUNT/2, fill=y) + 
  geom_tile(width=1, height=COUNT, color=NA) +
  scale_fill_viridis_c() +
  labs(title = "viridis") + 
  theme_void(15) + theme(legend.text = element_blank()) +
ggplot(data) +
  aes(x = x, y=COUNT/2, fill=y) + 
  geom_tile(width=1, height=COUNT, color=NA) +
  scale_fill_painbow() +
  labs(title = "painbow") +
  theme_void(15) + theme(legend.text = element_blank()) +

patchwork::plot_layout(ncol=4) +
patchwork::plot_annotation(
    title = "Three colormaps. Same data. Can you spot the harmonic?", 
    theme = theme(text = element_text(size=20)))

Feedback, issues, and contributions

Feedback, suggestions, issues, and contributions are all welcome! Please file an issue or pull request at https://github.com/steveharoz/painbow/issues

Citing Painbow

The XKCD comic deserves credit: https://xkcd.com/2537/

Please cite this library via:
Steve Haroz (2021). Painbow. R package version 1.0.1, https://github.com/steveharoz/painbow/.

About

Use XKCD's Painbow colormap with ggplot

Resources

License

Unknown, MIT licenses found

Licenses found

Unknown
LICENSE
MIT
LICENSE.md

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages