Introduction to coloRify

Maurits Unkel

10-15-2025

Introduction

🌈 Colorify makes color creation and modification intuitive and effortless. Colorify is lightweight and dependency-free yet combines functionality of popular color and visualization packages, including:

Why use coloRify?

Colorify is dependency-free, yet offers access to all popular palettes and color functionality described above!

If you are, like me, tired of errors complaining you need more colors than your palette contains? No problem! Colorify generates maximally different colors alongside custom palettes based on how many colors are requested.

Colorify enables effortless palette/color modification, based on the intuitive RGB and HSL color spaces.

How coloRify works

See the examples below for the following functionality:

Examples

To run coloRify, simply install the package from CRAN…

install.packages('colorify')

…or the development version from GitHub

pak::pkg_install('colorify', dependencies = TRUE, upgrade = TRUE)

Then load the library.

library(colorify)

Note that coloRify uses hexcolors (e.g.: ‘#FF0000FF’) and includes base R colors (e.g.: ‘red’) from grDevices:

grDevices::colors()

colorify()

basic

A basic call with just n(=10) colors requested. n takes an integer > 0.

colorify(n = 10, plot = TRUE)

#>  [1] "#E974E6FF" "#EEB723FF" "#48EEFCFF" "#D341F1FF" "#A37515FF" "#84EF83FF"
#>  [7] "#BBF963FF" "#221DE6FF" "#A77971FF" "#B38ED5FF"

See in the output above that coloRify returns a hexcolor vector.

seed

To show that a different seed yields different generated colors. Pass seed as an integer.

c <- colorify(10, plot = TRUE, seed = 1337)

custom colors

You can give custom colors and generate the rest, always have enough colors for plotting calls!

c <- colorify(colors = c("red", "white", "blue"), n = 5, plot = TRUE)

naming

Set names to the output hexcolor vector. colors_names takes a character vector of names the length of the amount of requested colors.

c <- colorify(colors = c("red", "white", "blue"), n = 5, colors_names = paste0('name', rep(1:5)), plot = TRUE)

ordering

Order the hexcolor output. Integer given as starting point for ordering, may be negative.

# set integer for the ordering starting position
c <- colorify(colors = c("red", "white", "blue"), n = 5, order = 2, plot = TRUE)

c <- colorify(colors = c("red", "white", "blue"), n = 5, order = 3, plot = TRUE)

# negative integer inverses the order 
c <- colorify(colors = c("red", "white", "blue"), n = 5, order = -1, plot = TRUE)

transparency

Set transparency of colors. alpha takes a float ranging between [0-1].

c <- colorify(colors = c("red", "white", "blue"), n = 5, alpha = .25, plot = TRUE)

custom palettes

You can supply an available palette in colors, that will be expanded up to requested n. 

c <- colorify(colors = c("Okabe-Ito"), plot = TRUE)

# note the 10th color is generated
c <- colorify(colors = c("Okabe-Ito"), plot = TRUE, n = 10)

# note that blue and yellow are cut, as only 10 colors are requested. 
c <- colorify(colors = c("Okabe-Ito", "red", "blue", "yellow"), plot = TRUE, n = 10)

gradients

Easy color gradients using the ‘nn’ parameter, also with custom and available palettes.

g1 <- colorify(colors = c("orange", "red", "white", "blue", "orange"), nn = 100, plot = TRUE)

g2 <- colorify(colors = c("pastel2"), nn = 100, plot = TRUE)

plotting

Plot options, default is circular output, plot = include ‘i’ for image and ‘l’ to plot color index as labels.

g1 <- colorify(colors = c("orange", "red", "white", "blue", "orange"), nn = 15, plot = 'l')
g1 <- colorify(colors = c("orange", "red", "white", "blue", "orange"), nn = 15, plot = 'i')
g1 <- colorify(colors = c("orange", "red", "white", "blue", "orange"), nn = 15, plot = 'il')

values and factors

Values and factors, let’s say you want your palette to be more or less RGB (red, green, blue)/HSL (hue, saturation, lightness), you can simply tweak their specific channels! Values are intuitively ranged between [0-100] (instead of 0-255). Factors are multiplicative.

The order in which values and factors are called matters, play around with combinations to obtain your ideal custom palettes.

Note that a gradient is made from the ‘n’ parameter here, as some palettes are actually called as functions internally.

g3 <- colorify(100, colors = c("viridis"), plot = T)

# r = red, f = factor: rf = 2 to multiply all red values 
g4 <- colorify(100, colors = c("viridis"), rf = 2, plot = T)

# v = value: rv = 50 to increase all red values by 50, on a scale between 0-100
g5 <- colorify(100, colors = c("viridis"), rv = 50, plot = T)

# first, multiply red values by 2, then increase red values by 50
g6 <- colorify(100, colors = c("viridis"), rf = 2, rv = 50, plot = T)

# first, increase red values by 50, then multiply red values by 2
g7 <- colorify(100, colors = c("viridis"), rv = 50, rf = 2, plot = T)

# float factor decrease values by multiplication
g8 <- colorify(100, colors = c("viridis"), bf = .5, plot = T)

# negative values work to decrease values 
g9 <- colorify(100, colors = c("viridis"), bv = -100, gv = -50, plot = T)

minimum and maximum values

When value and factor adjustments are made, the .min and .max parameters are used to set minimum and maximum RGB/HSL values.

g3 <- colorify(100, colors = c("viridis"), plot = T)

g8 <- colorify(100, colors = c("viridis"), bf = .5, plot = T)

# same factor decrease, yet limited by minimum value
g10 <- colorify(100, colors = c("viridis"), bf = .5, bmin = 40, plot = T)

# need factor/value change to use min/max value 
g11 <- colorify(100, colors = c("viridis"), bf = 1, bmax = 40, plot = T)

# can use them in combination
g12 <- colorify(100, colors = c("viridis"), bf = 1, bmin = 40, bmax = 40,  plot = T)

locking

The colors_lock can be used by locking specific colors by numerical index, starting from 1. colors_lock can also be used by patterning, as long as the nn % length of the boolean character == 0. colors_lock can be inversed by putting a ! in front of the given vector.

c <- colorify(colors = c("pastel2"), nn = 30, plot = TRUE)

# lock by index
c <- colorify(colors = c("pastel2"), nn = 30, colors_lock = c(4,5,6, 10,11,12), lf = .5, plot = T)

# inverse lock by index
c <- colorify(colors = c("pastel2"), nn = 30, colors_lock = -c(4:12), lf = .5, plot = T)

# lock by patterns
c <- colorify(colors = c("pastel2"), nn = 30, colors_lock = c(TRUE, FALSE), lf = .5, plot = T)

c <- colorify(colors = c("pastel2"), nn = 30, colors_lock = c(TRUE, FALSE, FALSE), lf = .5, plot = T)

mapping

colors_map takes a vector of values matching the vector of (generated) colors, returning a color_map function which can then be used to generate colors based on supplied values to it.

color_map <- colorify(colors = c('red', 'white', 'blue'), colors_map = c(0, 500, 1000))
# note the map is then given values to map back to the given color ranges from colors_map
m1 <- colorify(colors = color_map(0:1000), plot = T)

display_palettes()

all palettes

The base use of display_palettes() shows all available palettes in coloRify, that can be used with colorify(colors = c(…)).

display_palettes()

#>     Viridis-turbo         grDevices         grDevices         grDevices 
#>           "Turbo"         "Rainbow"            "Heat"         "Terrain" 
#>         grDevices         grDevices               hcl               hcl 
#>            "Topo"              "Cm"        "Pastel 1"          "Dark 2" 
#>               hcl               hcl               hcl               hcl 
#>          "Dark 3"           "Set 2"           "Set 3"            "Warm" 
#>               hcl               hcl               hcl               hcl 
#>            "Cold"        "Harmonic"         "Dynamic"           "Grays" 
#>               hcl               hcl               hcl               hcl 
#>     "Light Grays"         "Blues 2"         "Blues 3"       "Purples 2" 
#>               hcl               hcl               hcl               hcl 
#>       "Purples 3"          "Reds 2"          "Reds 3"        "Greens 2" 
#>               hcl               hcl               hcl               hcl 
#>        "Greens 3"            "Oslo"     "Purple-Blue"      "Red-Purple" 
#>               hcl               hcl               hcl               hcl 
#>        "Red-Blue"   "Purple-Orange"   "Purple-Yellow"     "Blue-Yellow" 
#>               hcl               hcl               hcl               hcl 
#>    "Green-Yellow"      "Red-Yellow"            "Heat"          "Heat 2" 
#>               hcl               hcl               hcl               hcl 
#>         "Terrain"       "Terrain 2"         "Viridis"          "Plasma" 
#>               hcl               hcl               hcl               hcl 
#>         "Inferno"          "Rocket"            "Mako"       "Dark Mint" 
#>               hcl               hcl               hcl               hcl 
#>            "Mint"          "BluGrn"            "Teal"         "TealGrn" 
#>               hcl               hcl               hcl               hcl 
#>           "Emrld"           "BluYl"        "ag_GrnYl"           "Peach" 
#>               hcl               hcl               hcl               hcl 
#>          "PinkYl"            "Burg"          "BurgYl"           "RedOr" 
#>               hcl               hcl               hcl               hcl 
#>           "OrYel"            "Purp"          "PurpOr"          "Sunset" 
#>               hcl               hcl               hcl               hcl 
#>         "Magenta"      "SunsetDark"       "ag_Sunset"          "BrwnYl" 
#>               hcl               hcl               hcl               hcl 
#>          "YlOrRd"          "YlOrBr"            "OrRd"         "Oranges" 
#>               hcl               hcl               hcl               hcl 
#>            "YlGn"          "YlGnBu"            "Reds"            "RdPu" 
#>               hcl               hcl               hcl               hcl 
#>            "PuRd"         "Purples"          "PuBuGn"            "PuBu" 
#>               hcl               hcl               hcl               hcl 
#>          "Greens"            "BuGn"            "GnBu"            "BuPu" 
#>               hcl               hcl               hcl               hcl 
#>           "Blues"         "Lajolla"           "Turku"          "Hawaii" 
#>               hcl               hcl               hcl               hcl 
#>          "Batlow"        "Blue-Red"      "Blue-Red 2"      "Blue-Red 3" 
#>               hcl               hcl               hcl               hcl 
#>       "Red-Green"    "Purple-Green"    "Purple-Brown"     "Green-Brown" 
#>               hcl               hcl               hcl               hcl 
#>   "Blue-Yellow 2"   "Blue-Yellow 3"    "Green-Orange"    "Cyan-Magenta" 
#>               hcl               hcl               hcl               hcl 
#>          "Tropic"            "Broc"            "Cork"             "Vik" 
#>               hcl               hcl               hcl               hcl 
#>          "Berlin"          "Lisbon"          "Tofino"        "ArmyRose" 
#>               hcl               hcl               hcl               hcl 
#>           "Earth"            "Fall"          "Geyser"        "TealRose" 
#>               hcl               hcl               hcl               hcl 
#>           "Temps"            "PuOr"            "RdBu"            "RdGy" 
#>               hcl               hcl               hcl               hcl 
#>            "PiYG"            "PRGn"            "BrBG"          "RdYlBu" 
#>               hcl               hcl               hcl               hcl 
#>          "RdYlGn"        "Spectral"        "Zissou 1"         "Cividis" 
#>               hcl               pal               pal               pal 
#>            "Roma"              "R3"              "R4"         "ggplot2" 
#>               pal               pal               pal               pal 
#>       "Okabe-Ito"          "Accent"          "Dark 2"          "Paired" 
#>               pal               pal               pal               pal 
#>        "Pastel 1"        "Pastel 2"           "Set 1"           "Set 2" 
#>               pal               pal               pal               pal 
#>           "Set 3"      "Tableau 10" "Classic Tableau"   "Polychrome 36" 
#>               pal 
#>        "Alphabet"

n palettes

The n parameter here is used to show the amount of colors per palette.

p1 <- display_palettes(10)

# display 100 colors per palette
p2 <- display_palettes(100)

palettes by index

The i_palettes parameter can also be passed numeric integers to get a more clear palette view.

# display palettes by index
display_palettes(i_palettes = 50:75)

#>          hcl          hcl          hcl          hcl          hcl          hcl 
#>      "BluYl"   "ag_GrnYl"      "Peach"     "PinkYl"       "Burg"     "BurgYl" 
#>          hcl          hcl          hcl          hcl          hcl          hcl 
#>      "RedOr"      "OrYel"       "Purp"     "PurpOr"     "Sunset"    "Magenta" 
#>          hcl          hcl          hcl          hcl          hcl          hcl 
#> "SunsetDark"  "ag_Sunset"     "BrwnYl"     "YlOrRd"     "YlOrBr"       "OrRd" 
#>          hcl          hcl          hcl          hcl          hcl          hcl 
#>    "Oranges"       "YlGn"     "YlGnBu"       "Reds"       "RdPu"       "PuRd" 
#>          hcl          hcl 
#>    "Purples"     "PuBuGn"
display_palettes(i_palettes = c(1,5,10,20,40,100,119))

#> Viridis-turbo     grDevices           hcl           hcl           hcl 
#>       "Turbo"        "Topo"       "Set 2"   "Purples 2"      "Plasma" 
#>           hcl           hcl 
#>         "Vik"    "Zissou 1"

bordered palettes

Visualize palettes with borders around individual colors.

display_palettes(n = 10, i_palettes = 1:10, border = TRUE)

#> Viridis-turbo     grDevices     grDevices     grDevices     grDevices 
#>       "Turbo"     "Rainbow"        "Heat"     "Terrain"        "Topo" 
#>     grDevices           hcl           hcl           hcl           hcl 
#>          "Cm"    "Pastel 1"      "Dark 2"      "Dark 3"       "Set 2"

ggplot2 bindings

These functions are bindings similar to the ggplot2 scale_* functions, to use them ggplot2 has to be installed and loaded.

install.packages('ggplot2')
library(ggplot2)

scale_color_colorify()

non-discrete

dsub <- subset(ggplot2::diamonds, x > 5 & x < 6 & y > 5 & y < 6)
dsub$diff <- with(dsub, sqrt(abs(x - y)) * sign(x - y))

ggplot2::ggplot(dsub, ggplot2::aes(x, y, colour = diff)) + 
  ggplot2::geom_point() + 
  scale_color_colorify(n = 4, colors = 'viridis') + 
  ggplot2::theme_bw()

discrete

p <- ggplot2::ggplot(mtcars, ggplot2::aes(wt, mpg))

p + ggplot2::geom_point(size = 4, ggplot2::aes(colour = factor(cyl))) +
  ggplot2::theme_bw() + 
  scale_color_colorify(discrete = TRUE, colors = c('red', 'blue', 'yellow'))

scale_fill_colorify()

non-discrete

dat <- data.frame(x = rnorm(10000), y = rnorm(10000))

ggplot2::ggplot(dat, ggplot2::aes(x = x, y = y)) +
  ggplot2::geom_hex() + ggplot2::coord_fixed() +
  scale_fill_colorify(colors = 'viridis', n = 4) + ggplot2::theme_bw()

discrete

df <- data.frame(category = c("A", "B", "C", "D"), value = c(10, 23, 15, 8))

ggplot2::ggplot(df, ggplot2::aes(x = category, y = value, fill = category)) +
  ggplot2::geom_bar(stat = "identity") + 
  scale_fill_colorify(discrete = TRUE, colors = 'viridis')

colortistry()

My colorful monstrosity I contribute to the #Rtistry community! I heartily welcome creative contributions using coloRify <3

colors_list <- list()
for (i in seq(100)) {
  colors_list[[i]] <- colorify(n = 100, colors = "rainbow", colors_lock = rep(c(T,F,F,F,F), 20), hf = 25/i, lf = i/20)
  if (i %% 3) colors_list[[i]] <- colorify(n = 100, colors = "rainbow", colors_lock = rep(c(F,F,T,F,F), 20), hf = 30/i, lf = i/20)
  if (i %% 4) colors_list[[i]] <- colorify(n = 100, colors = "rainbow", colors_lock = rep(c(F,F,F,T,F), 20), hf = 50/i, lf = i/40)
  if (i %% 5) colors_list[[i]] <- colorify(n = 100, colors = "rainbow", colors_lock = rep(c(F,T,F,F,F), 20), hf = 50/i, sf = i/50)
}
colortistry(colors_list)

# and with borders
colortistry(colors_list, border_color = 'black')

Information

A thank you for your time and effort in using coloRify, I hope it may aid you in COOLORing your visualizations!

Contact

Colorify was developed by Maurits Unkel at the Erasmus Medical Center in the department of Psychiatry. Source code is available through GitHub: https://github.com/mauritsunkel/colorify Questions regarding coloRify can be sent to:

License

Colorify is licensed under Apache 2.0.

Issues and contributions

For issues and contributions, please find the coloRify Github page: https://github.com/mauritsunkel/colorify/issues

FAQ

Q: How can I easily test my coloRify palettes on actual visualizations?

Session info

sessionInfo()
#> R version 4.5.0 (2025-04-11 ucrt)
#> Platform: x86_64-w64-mingw32/x64
#> Running under: Windows 11 x64 (build 26200)
#> 
#> Matrix products: default
#>   LAPACK version 3.12.1
#> 
#> locale:
#> [1] LC_COLLATE=C                          
#> [2] LC_CTYPE=English_United States.utf8   
#> [3] LC_MONETARY=English_United States.utf8
#> [4] LC_NUMERIC=C                          
#> [5] LC_TIME=English_United States.utf8    
#> 
#> time zone: Europe/Amsterdam
#> tzcode source: internal
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] colorify_0.1.2
#> 
#> loaded via a namespace (and not attached):
#>  [1] vctrs_0.6.5        cli_3.6.5          knitr_1.50         rlang_1.1.6       
#>  [5] xfun_0.53          generics_0.1.4     S7_0.2.0           jsonlite_2.0.0    
#>  [9] labeling_0.4.3     glue_1.8.0         htmltools_0.5.8.1  sass_0.4.10       
#> [13] scales_1.4.0       rmarkdown_2.30     grid_4.5.0         tibble_3.3.0      
#> [17] evaluate_1.0.5     jquerylib_0.1.4    fastmap_1.2.0      yaml_2.3.10       
#> [21] lifecycle_1.0.4    compiler_4.5.0     dplyr_1.1.4        RColorBrewer_1.1-3
#> [25] pkgconfig_2.0.3    rstudioapi_0.17.1  lattice_0.22-7     farver_2.1.2      
#> [29] digest_0.6.37      R6_2.6.1           tidyselect_1.2.1   pillar_1.11.1     
#> [33] magrittr_2.0.4     bslib_0.9.0        withr_3.0.2        tools_4.5.0       
#> [37] gtable_0.3.6       hexbin_1.28.5      ggplot2_4.0.0      cachem_1.1.0