Search code examples
rcolor-theory

Best Practice for Sorting Distinct Hex Colors in R


Update: Based on answers, I am researching ColorBrewer and Colorspace R packages. Due to request, I am re-writing my original question.

Question: How to best sort individual, predefined hex colors so that similar colors are grouped together, yet ordered starting with most warm colors, to light colors to coolest colors. I wish to incorporate this in future version of RanglaPunjab R package

For example Cynthia Brewer's spectral colors ( reds, blues, greens, etc are together in single stream) illustrates this.

I'm asking for Logic, rather than Code.

enter image description here


So far, I attempted to sort by Hue, Hue + Value, Hue * Value, based on this article, https://www.alanzucconi.com/2015/09/30/colour-sorting/

This question borderlines between R and Color Theory.

Code at the end of this post sorts colors by Hue, Hue + Value, Hue * Value (depends on what you comment or uncomment).

Please tell me (or give hint) on how get similar results as Cynthia Brewer's spectral colors

Unordered Colors:

enter image description here

Ordered based on Hue:

enter image description here

Ordered based on Hue + Value:

enter image description here

Ordered based on Hue * Value:

enter image description here

For Reference, here is original, unordered palette

> oldPal
 [1] "#22325f" "#88ce64" "#fbd234" "#b8091f" "#682f4e" "#fdea6e" "#4aec6a" "#fb7894" "#f13111" "#2584a0"
[11] "#6fa42c" "#db3717" "#051a8d" "#ef38a7" "#202c3d"

Converted to HSV, then transposed

> tHSVcol
               h         s         v
 [1,] 0.62295082 0.6421053 0.3725490
 [2,] 0.27672956 0.5145631 0.8078431
 [3,] 0.13232831 0.7928287 0.9843137
 [4,] 0.97904762 0.9510870 0.7215686
 [5,] 0.90935673 0.5480769 0.4078431
 [6,] 0.14452214 0.5652174 0.9921569
 [7,] 0.36625514 0.6864407 0.9254902
 [8,] 0.96437659 0.5219124 0.9843137
 [9,] 0.02380952 0.9294606 0.9450980
[10,] 0.53794038 0.7687500 0.6274510
[11,] 0.24027778 0.7317073 0.6431373
[12,] 0.02721088 0.8949772 0.8588235
[13,] 0.64093137 0.9645390 0.5529412
[14,] 0.89890710 0.7656904 0.9372549
[15,] 0.59770115 0.4754098 0.2392157

R Code

library(RanglaPunjab)

RenderPal <- function(x,name){

  if ((missing(x)) || (missing(name))){
    stop("Internal error, please troubleshoot")
  }
  n <- length(x)
  old <- graphics::par(mar = c(0.5, 0.5, 0.5, 0.5))
  on.exit(graphics::par(old))

  graphics::image(1:n, 1, as.matrix(1:n), col = x,
                  ylab = "", xaxt = "n", yaxt = "n", bty = "n")
  graphics::rect(0, 0.9, n + 1, 1.1, col = grDevices::rgb(1, 1, 1, 0.8), border = NA)
  graphics::text((n + 1) / 2, 1, labels = name, cex = 2, family = "serif")
}

i <- NULL
oldPal <- NULL
rankorder <- NULL
orderedPal<- NULL
RGBcol <- NULL
HSVcol <- NULL
tHSVcol <- NULL
orderType <- NULL

# Paint the colors
PaintPalette("Teej","Gidha","Jutti3")

# Store the hex values
oldPal <- MergePalette("Teej","Gidha","Jutti3")

# Print hex values
oldPal

# Convert Hex to RGB
RGBcol <- col2rgb(oldPal)

# Print RGB values
RGBcol

# Convert RGB to HSV
HSVcol <- rgb2hsv(RGBcol)

# Print matrix
HSVcol

# Transpose matrix
tHSVcol <- t(HSVcol)

# Print matrix
tHSVcol


# Uncomment following to order by Hue, then Saturation, then Value
rankorder <- order(tHSVcol[,1],tHSVcol[,2],tHSVcol[,3])
orderType <- "Hue Ordering"

# Uncomment following to order by hANDv = Hue + Value
# hANDv <- apply(tHSVcol[,c(1,3)],1,sum)
# rankorder <- order(hANDv)
# orderType <- "Hue + Value Ordering"

# Uncomment following to order by hPRODv = Hue * Value
# hPRODv <- apply(tHSVcol[,c(1,3)],1,prod)
# rankorder <- order(hPRODv)
# orderType <- "Hue * Value Ordering"

rankorder

for (i in 1:length(rankorder)){
  orderedPal[i] <- oldPal[rankorder[i]]
}

# Print old, unordered palette
oldPal

# Print new, ordered palette
orderedPal

RenderPal(oldPal, "Unordered Palette")
RenderPal(orderedPal, orderType)

Solution

  • Generally, you'll have to either use the ordering of one or more RGBA combinations, create your own objects and establish an order method, or use a pre-existing package.

    Cynthia Brewer has an excellent package, RColorBrewer that uses different color palettes that are ordered, divergent, or unordered. Some of them are optimized for common color blindness conditions.

    library(RColorBrewer)
    display.brewer.all()# to see all of them
    

    enter image description here

    brewer.pal.info is a data frame with information about each palette

    head(brewer.pal.info)
    #          maxcolors category colorblind
    # BrBG        11      div       TRUE
    # PiYG        11      div       TRUE
    # PRGn        11      div       TRUE
    # PuOr        11      div       TRUE
    # RdBu        11      div       TRUE
    # RdGy        11      div      FALSE