I’m happy to announce my newest package prismatic which facilitates simple manipulations of colors. I had been working on this package online and offline for some time, but the promise of easy manipulation of mapped data in ggplot2 forced me to get some work done to get this package out before ggplot2 version 3.3.0. (as of time of writing.)
This post will go over some of the finer details with lots of pretty pictures!
The prismatic package is fairly low dependency with only 1 import being farver for lightning fast conversion between color spaces. I have also loaded the colorspace package, from which some of the following functions have been inspired. I will use colorspace to enable plotting of multiple color palettes side by side, but I will not showcase the code each time. Go to the end of the post for example code for comparison plots.
library(prismatic) library(colorspace) # for plotting functions library(magrittr) # for the glorious pipe
If you have seen my work, you will properly know that I like colors alot! But being also to quickly inspect some colors have always been a little too much work. Now all you have to do it pass your colors to
colour() for our friends across the pond) to get a
rainbow(10) %>% color() %>% plot()
hcl.colors(25) %>% color() %>% plot()
scico::scico(256, palette = "buda") %>% color() %>% plot()
Which I would like to think is one of the main features of the package. If you happens to have crayon available you will see a approximation of the colors with a filled in background (this limited to 256 colors so you milage might very, when in doubt use
This is the extent of what the color object can do.
The second star of the package is the collection of functions to manipulate the colors. All these functions have a couple of things in common.
clr_for easy auto completion in your favorite IDE.
these two facts make the function super pipe friendly.
The two functions
clr_desaturate() both modifies the saturation of a color. It takes a single additional argument to specifying the degree of which the (de)saturation should occur. These values should be between 0(nothing happens) and 1(full on power!).
notice how you don’t have to call
color() on the output of
clr_desaturate() as it already returns a colors object.
hcl.colors(10, "plasma") %>% clr_desaturate(0.8) %>% plot()
Example done with Mango palette from LaCroixColoR package.
Turns out there is a lot of different ways to turn colors into grayscale. Prismatic has implemented a handful of these. Notice how the viridis palette is still working once you have it transformed to black and white.
hcl.colors(10) %>% clr_greyscale() %>% plot()
Be advised that not all of these methods are meant to be perceptually uniform.
Negation of a color is pretty simple. it will just pick the opposite color in RGB space.
terrain.colors(10) %>% clr_negate() %>% plot()
Mixing is just adding colors together. Thus my mixing a color with red would make a color more red.
rainbow(10) %>% clr_mix("red") %>% plot()
clr_rotate() function will take a color and rotate its hue, which is a way walk around the rainbow.
terrain.colors(10) %>% clr_rotate(90) %>% plot()
also includes 3 functions (
clr_tritan()) to simulate colorblindness. These functions has a
severity argument to control the strength of the deficiency.
hcl.colors(10) %>% clr_deutan() %>% plot()
Lastly we have functions to simulate lightness and darkness. This is surprisingly hard to do and no one way works great all the time. Please refer to the excellent colorspace paper for more information. These functions (
clr_darken()) also include a
space argument to determine the space in which to perform the transformation. Please try each of these to find the optimal method for your use case.
rainbow(10) %>% clr_darken() %>% plot()
swatchplot( list( saturate = rbind("0" = clr_rotate(terrain.colors(10), 0), "60" = clr_rotate(terrain.colors(10), 60), "120" = clr_rotate(terrain.colors(10), 120), "180" = clr_rotate(terrain.colors(10), 180), "240" = clr_rotate(terrain.colors(10), 240), "300" = clr_rotate(terrain.colors(10), 300)), desaturate = rbind("0" = clr_rotate(hcl.colors(10), 0), "60" = clr_rotate(hcl.colors(10), 60), "120" = clr_rotate(hcl.colors(10), 120), "180" = clr_rotate(hcl.colors(10), 180), "240" = clr_rotate(hcl.colors(10), 240), "300" = clr_rotate(hcl.colors(10), 300)) ), nrow = 7, line = 2.5 )