[R] General means of matching a color specification to an official R color name

Bryan Hanson hanson at depauw.edu
Tue Oct 13 22:43:16 CEST 2009

Hello List Dwellers:

I¹ve looked around quite a bit, but don¹t quite see an answer that I

I¹m looking for a way to take any kind of color specification (rgb, hsv,
hcl, hex) and match it to the n-nearest R official color names.  Clearly it
is easy to interconvert different specification schemes and color spaces,
but matching to the name seems a bit trickier.  Seems like if one has a
specification, it could be fuzzy-matched to the list of official R colors
expressed in the same specification.  Unfortunately, I don¹t know much about
fuzzy matching.

For example, following some examples I found in the archives and the wiki, I
wrote this little function to create a table of official R colors and sort
it if desired:

colorSpecTable <- function(col = colors(), sort = NULL){
    rgbcodes <- t(col2rgb(col))
    names <- col
    hex <- col2hex(col)
    df <- data.frame(name = names, hex.code = hex, rgbcodes)
   # additional elements for other color spaces could be added
    if (!identical(sort, NULL)) df <- sort.data.frame(df, by = sort)

Note that sort.data.frame is from the R-wiki and is appended below.  Is
there a clever way to search a table created by this function, and identify
the n-closest colors based upon some reasonable criteria?  What I hope for
is something like this:

colorMatch <- function(hex = NULL, n, plot = HOPEFULLY) {
    df.rgb <- colorSpecTable(sort = ~red+green+blue) # master table
    # now search for the n closest matches of hex in df.rgb$hex.code
    # perhaps hex should be converted into a different color space 1st
    # eventually would like to display matches side by side w/hex

Thanks as always.  Bryan
Bryan Hanson
Acting Chair
Professor of Chemistry & Biochemistry
DePauw University, Greencastle IN USA

sort.data.frame <- function(x, by){
    # Author: Kevin Wright
    # with some ideas from Andy Liaw
    # Found in the R Wiki

    # x: A data.frame
    # by: A one-sided formula using + for ascending and - for descending
    # Sorting is left to right in the formula
    # Useage is:
    # library(nlme);
    # data(Oats)
    # sort(Oats, by= ~nitro-Variety)

    if(by[[1]] != "~")
        stop("Argument 'by' must be a one-sided formula.")

    # Make the formula into character and remove spaces
    formc <- as.character(by[2])
    formc <- gsub(" ", "", formc)
    # If the first character is not + or -, add +
    if(!is.element(substring(formc, 1, 1), c("+", "-")))
        formc <- paste("+", formc, sep = "")

    # Extract the variables from the formula
    vars <- unlist(strsplit(formc, "[\\+\\-]"))
    vars <- vars[vars != ""] # Remove any extra "" terms

    # Build a list of arguments to pass to "order" function
    calllist <- list()
    pos <- 1 # Position of + or -
    for(i in 1:length(vars)){
        varsign <- substring(formc, pos, pos)
        pos <- pos + 1 + nchar(vars[i])
        if(is.factor(x[, vars[i]])){
            if(varsign == "-") {
                calllist[[i]] <- -rank(x[, vars[i]])
            } else {
                calllist[[i]] <- rank(x[, vars[i]])
        } else {
            if(varsign == "-") {
                calllist[[i]] <- -x[, vars[i]]
            } else {
                calllist[[i]] <- x[,vars[i]]
    return(x[do.call("order", calllist), ])

More information about the R-help mailing list