Short question, if I have a string, how can I test if that string is a valid color representation in R
?
Two things I tried, first uses the function col2rgb()
to test if it is a color:
isColor <- function(x) { res <- try(col2rgb(x),silent=TRUE) return(!"try-error"%in%class(res)) } > isColor("white") [1] TRUE > isColor("#000000") [1] TRUE > isColor("foo") [1] FALSE
Works, but doesn't seem very pretty and isn't vectorized. Second thing is to just check if the string is in the colors()
vector or a #
followed by a hexadecimal number of length 4 to 6:
isColor2 <- function(x) { return(x%in%colors() | grepl("^#(\\d|[a-f]){6,8}$",x,ignore.case=TRUE)) } > isColor2("white") [1] TRUE > isColor2("#000000") [1] TRUE > isColor2("foo") [1] FALSE
Which works though I am not sure how stable it is. But it seems that there should be a built in function to make this check?
The length of the hexadecimal color code should be either 6 or 3, excluding '#' symbol. For example: #abc, #ABC, #000, #FFF, #000000, #FF0000, #00FF00, #0000FF, #FFFFFF are all valid Hexadecimal color codes.
Yes, in hexadecimal, things like A, B, C, D, E, and F are considered numbers, not letters. That means that 200 is a perfectly valid hexadecimal number just as much as 2FA is also a valid hex number.
String has great warmth and richnessString is a great colour - always choose delicate shades from Farrow and Ball but this time I wanted something with a litte more colour depth. I wasn't disappointed. It has a changing face depending on the time of day and the natural light levels entering the room.
regex = "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$"; Where: ^ represents the starting of the string. # represents the hexadecimal color code must start with a '#' symbol.
Your first idea (using col2rgb()
to test color names' validity for you) seems good to me, and just needs to be vectorized. As for whether it seems pretty or not ... lots/most R functions aren't particularly pretty "under the hood", which is a major reason to create a function in the first place! Hides all those ugly internals from the user.
Once you've defined areColors()
below, using it is easy as can be:
areColors <- function(x) { sapply(x, function(X) { tryCatch(is.matrix(col2rgb(X)), error = function(e) FALSE) }) } areColors(c(NA, "black", "blackk", "1", "#00", "#000000")) # <NA> black blackk 1 #00 #000000 # TRUE TRUE FALSE TRUE FALSE TRUE
?par
gives a thorough description of the ways in which colours can be specified in R. Any solution to a valid colour must consider:
colors()
"#RRGGBBAA
specifying the red, green, blue and alpha channels. The Alpha channel is for transparency, which not all devices support and hence whilst it is valid to specify a colour in this way with 8 hex values it may not be valid on a specific device.NA
is a valid "colour". It means transparent, but as far as R is concerned it is a valid colour representation."transparent"
is also valid, but not in colors()
, so that needs to be handled as well1
is a valid colour representation as it is the index of a colour in a small palette of colours as returned by palette()
> palette() [1] "black" "red" "green3" "blue" "cyan" "magenta" "yellow" [8] "gray"
Hence you need to cope with 1:8
. Why is this important, well ?par
tells us that it is also valid to represent the index for these colours as a character hence you need to capture "1"
as a valid colour representation. However (as noted by @hadley in the comments) this is just for the default palette. Another palette may be used by a user, in which case you will have to consider a character index to an element of a vector of the maximum allowed length for your version of R.
Once you've handled all those you should be good to go ;-)
To the best of my knowledge there isn't a user-visible function that does this. All of this in buried away inside the C code that does the plotting; very quickly you end up in .Internal(....)
land and there be dragons!
[To be pedantic #000000
isn't a colour name in R.]
The only colour names R knows are those returned by colors()
. Yes, #000000
is one of the colour representations that R understands but you specifically ask about a name and the definitive list or solution is x %in% colors()
as you have in your second example.
This is about as stable as it gets. When you use a colour like col = "goldenrod"
, internally R matches this with a "proper" representation of the colour for whichever device you are plotting on. color()
returns the list of colour names that R can do this looking up for. If it isn't in colors()
then it isn't a colour name.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With