38

简短的问题,如果我有一个字符串,我如何测试该字符串是否是有效的颜色表示R

我尝试了两件事,首先使用该函数col2rgb()来测试它是否是一种颜色:

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

有效,但看起来不是很漂亮,也没有矢量化。第二件事是检查字符串是否在colors()向量中或#后跟长度为 4 到 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

虽然我不确定它有多稳定,但它有效。但似乎应该有一个内置函数来进行这个检查?

4

2 回答 2

25

您的第一个想法(col2rgb()用于测试颜色名称对您的有效性)对我来说似乎很好,只需要矢量化。至于它看起来是否漂亮......很多/大多数R函数在“引擎盖下”并不是特别漂亮,这是首先创建一个函数的主要原因!对用户隐藏所有那些丑陋的内部结构。

一旦你在areColors()下面定义,使用它就很容易了:

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 
于 2012-11-08T14:21:59.880 回答
6

更新,鉴于编辑

?par详细描述了在 R 中可以指定颜色的方式。任何有效颜色的解决方案都必须考虑:

  1. 列出的命名颜色colors()
  2. 作为一个字符的十六进制表示形式,"#RRGGBBAA指定红色、绿色、蓝色和 alpha 通道。Alpha 通道用于透明度,并非所有设备都支持,因此虽然使用 8 个十六进制值以这种方式指定颜色是有效的,但它在特定设备上可能无效。
  3. NA是有效的“颜色”。它表示透明,但就 R 而言,它是一种有效的颜色表示。
  4. 同样"transparent"也是有效的,但不是 in colors(),所以也需要处理
  5. 1是一个有效的颜色表示,因为它是一个小调色板中的颜色索引,由palette()

    > palette()
    [1] "black"   "red"     "green3"  "blue"    "cyan"    "magenta" "yellow" 
    [8] "gray"
    

    因此,您需要应对1:8. 为什么这很重要,很好地?par告诉我们将这些颜色的索引表示为字符也是有效的,因此您需要将其捕获"1"为有效的颜色表示。但是(正如@hadley 在评论中指出的那样)这适用于默认调色板。用户可能会使用另一个调色板,在这种情况下,您必须考虑对您的 R 版本允许的最大长度的向量元素的字符索引。

一旦你处理了所有这些,你应该好好去;-)

据我所知,没有用户可见的功能可以做到这一点。所有这些都隐藏在执行绘图的 C 代码中;很快你就会在.Internal(....)陆地上出现龙!


原来的

[迂腐#000000 不是R中的颜色名称。]

R 知道的唯一颜色名称是由colors(). 是的,#000000是 R 理解的颜色表示之一,但您特别询问名称,最终列表或解决方案x %in% colors()与您在第二个示例中的一样。

这几乎是稳定的。当您使用类似的颜色时col = "goldenrod",R 在内部将其与您正在绘制的任何设备的颜色的“正确”表示相匹配。color()返回 R 可以查找的颜色名称列表。如果它不在,colors()那么它不是颜色名称。

于 2012-11-08T13:14:07.347 回答