【问题标题】:How to generate a number of most distinctive colors in R?如何在 R 中生成许多最独特的颜色?
【发布时间】:2013-02-23 07:46:06
【问题描述】:

我正在绘制一个分类数据集,并希望使用独特的颜色来表示不同的类别。给定一个数字n,我怎样才能得到n R 中最具特色的颜色数量?谢谢。

【问题讨论】:

标签: r colors palette color-palette colorbrewer


【解决方案1】:

您可以使用来自 base 的 colorRampPaletteRColorBrewer 包:

使用colorRampPalette,您可以按如下方式指定颜色:

colorRampPalette(c("red", "green"))(5)
# [1] "#FF0000" "#BF3F00" "#7F7F00" "#3FBF00" "#00FF00"

您也可以提供十六进制代码:

colorRampPalette(c("#3794bf", "#FFFFFF", "#df8640"))(5)
# [1] "#3794BF" "#9BC9DF" "#FFFFFF" "#EFC29F" "#DF8640"
# Note that the mid color is the mid value...

使用RColorBrewer,您可以使用现有调色板中的颜色:

require(RColorBrewer)
brewer.pal(9, "Set1")
# [1] "#E41A1C" "#377EB8" "#4DAF4A" "#984EA3" "#FF7F00" "#FFFF33" "#A65628" "#F781BF"
# [9] "#999999"

查看RColorBrewer 包以获取其他可用的调色板。希望这会有所帮助。

【讨论】:

  • 谢谢。我喜欢最后一个选项brewer.pal。但它最多只能有 9 种颜色。我实际上有超过 9 个类别。第一个替代方案会生成渐变颜色,它不像我想要的那样与众不同。
  • 您将无法选择许多“独特”的颜色。我想你最多可以得到12个。您应该查看colorbrewer2.org 并获取颜色(如果我是对的,有 1 12 个调色板)。
  • 寻找超过 12 种不同的颜色会很困难 - 我想在 colorbrewer 页面上已经讨论过了
  • 没关系,只要它们是可用的“最”独特的颜色,即使数量增加,它们也会变得不那么独特。
  • 如果您的问题是在分配给相邻类别时并排显示相似的颜色(就像彩虹调色板一样),那么您可以简单地将彩虹输出随机化为: Rainbow(n=10 )[样本(10)]
【解决方案2】:

这里有几个选项:

  1. 看看palette函数:

     palette(rainbow(6))     # six color rainbow
     (palette(gray(seq(0,.9,len = 25)))) #grey scale
    
  2. 还有colorRampPalette 函数:

     ##Move from blue to red in four colours
     colorRampPalette(c("blue", "red"))( 4) 
    
  3. 查看RColorBrewer package(和website)。如果您想要不同的颜色,请在网站上选择diverging。例如,

     library(RColorBrewer)
     brewer.pal(7, "BrBG")
    
  4. I want hue 网站提供了许多漂亮的调色板。同样,只需选择您需要的调色板。例如,您可以从网站获取 rgb 颜色并制作自己的调色板:

     palette(c(rgb(170,93,152, maxColorValue=255),
         rgb(103,143,57, maxColorValue=255),
         rgb(196,95,46, maxColorValue=255),
         rgb(79,134,165, maxColorValue=255),
         rgb(205,71,103, maxColorValue=255),
         rgb(203,77,202, maxColorValue=255),
         rgb(115,113,206, maxColorValue=255)))
    

【讨论】:

  • 感谢您的回答。它会产生颜色,但有些颜色彼此之间不是很独特。也许我应该在我的问题中更多地强调这一点。
  • @RNAer 我已经更新了我的答案。您可以使用建议 3 和 4 来获得发散的调色板。
  • I want hue 是一个很棒的网站。这正是我想要的。给定一个数字,如何生成颜色数量的调色板。但是我们可以在 R 中自动完成吗?
  • 太棒了。但是,该网站背后有很多机器。我认为重新实施不会是微不足道的。如果i want hue 有一个允许自动查询它的 API,那就太好了(也许确实如此——我没有花很长时间寻找)
  • @BenBolker - 我已经为i want huehere 的 R 版本做了一个要点。可以提高效率(例如,通过将颜色样本保存为数据对象),但总体思路就在那里。 (使用devtools::source_gist('45b49da5e260a9fc1cd7') 加载)
【解决方案3】:

我加入了 RColorBrewer 包中的所有定性调色板。定性调色板应该提供 X 种最独特的颜色。当然,将它们混合到一个调色板中也会产生相似的颜色,但这是我能得到的最好的颜色(74 种颜色)。

library(RColorBrewer)
n <- 60
qual_col_pals = brewer.pal.info[brewer.pal.info$category == 'qual',]
col_vector = unlist(mapply(brewer.pal, qual_col_pals$maxcolors, rownames(qual_col_pals)))
pie(rep(1,n), col=sample(col_vector, n))

其他解决方案是:从图形设备中获取所有 R 颜色并从中采样。我删除了灰色阴影,因为它们太相似了。这给出了 433 种颜色

color = grDevices::colors()[grep('gr(a|e)y', grDevices::colors(), invert = T)]

pie(rep(1,n), col=sample(color, n))

有200种颜色n = 200:

pie(rep(1,n), col=sample(color, n))

【讨论】:

  • 是否有可能将col中的十六进制代码转换为相应的颜色名称?
  • @Prradep col 你的意思是?来自图形设备的color 有名字。如果您的意思是一般来说,并非所有十六进制代码都有对应的颜色名称(grDevices 中只有 433 种颜色,但十六进制代码更多)
  • 我在您的代码 sn-p 中提到了 RColorBrewer 包中的 col=sample(col_vector, n)。例如,如何查找#B3E2CD, #E78AC3, #B3DE69 的颜色名称可从sample(col_vector,3) 获得。或者,如何找到brewer.pal 函数给出的所有十六进制代码及其颜色名称。
  • @Prradep,因为RColorBrewer 调色板不是从grDevices 颜色派生的,它有名称映射,但只是十六进制代码,据我所知,你不能用RColorBrewer 调色板做到这一点,甚至是定性的。
  • @ytu 那么颜色无法区分。如果绝对有必要,我建议在 R 中寻找“渐变创建”,然后使用颜色的随机采样。但是从颜色到因子的映射是行不通的,人类的感知可能会处理 20 到 40 种颜色,其余的差别不大。
【解决方案4】:

你也可以试试randomcoloR package:

library(randomcoloR)
n <- 20
palette <- distinctColorPalette(n)

您可以看到在饼图中可视化时选择了一组高度不同的颜色(正如此处其他答案所建议的那样):

pie(rep(1, n), col=palette)

以 50 种颜色的饼图显示:

n <- 50
palette <- distinctColorPalette(n)
pie(rep(1, n), col=palette)

【讨论】:

  • 谢谢。我必须使用unname(distinctColorPalette(n)) 才能使这项工作与 ggplot 一起使用。我猜 ggplot 需要一个未命名的向量。 col_vector &lt;- unname(distinctColorPalette(n)) 然后... + scale_color_manual(values=col_vector) ...
【解决方案5】:

我建议使用外部资源来制作大型调色板。

http://tools.medialab.sciences-po.fr/iwanthue/

具有根据各种参数组合任意大小调色板的服务,并且

https://graphicdesign.stackexchange.com/questions/3682/where-can-i-find-a-large-palette-set-of-contrasting-colors-for-coloring-many-d/3815

从图形设计师的角度讨论一般问题,并提供大量可用调色板的示例。

要从 RGB 值组成调色板,您只需复制向量中的值,例如:

colors37 = c("#466791","#60bf37","#953ada","#4fbe6c","#ce49d3","#a7b43d","#5a51dc","#d49f36","#552095","#507f2d","#db37aa","#84b67c","#a06fda","#df462a","#5b83db","#c76c2d","#4f49a3","#82702d","#dd6bbb","#334c22","#d83979","#55baad","#dc4555","#62aad3","#8c3025","#417d61","#862977","#bba672","#403367","#da8a6d","#a79cd4","#71482c","#c689d0","#6b2940","#d593a7","#895c8b","#bd5975")

【讨论】:

    【解决方案6】:

    不是对 OP 问题的回答,但值得一提的是,viridis 包具有良好的顺序数据调色板。它们在感知上是统一的、色盲安全且易于打印。

    要获取调色板,只需安装包并使用函数viridis_pal()。有“A”、“B”、“C”、“D”四个选项可供选择

    install.packages("viridis")
    library(viridis)
    viridis_pal(option = "D")(n)  # n = number of colors seeked
    

    还有一个精彩的演讲解释了 YouTube 上优秀色彩图的复杂性:

    A Better Default Colormap for Matplotlib | SciPy 2015 | Nathaniel Smith and Stéfan van der Walt

    【讨论】:

    • 这不太适合独特的颜色。
    【解决方案7】:

    我找到了一个提供 20 种独特颜色列表的网站:https://sashat.me/2017/01/11/list-of-20-simple-distinct-colors/

    col_vector<-c('#e6194b', '#3cb44b', '#ffe119', '#4363d8', '#f58231', '#911eb4', '#46f0f0', '#f032e6', '#bcf60c', '#fabebe', '#008080', '#e6beff', '#9a6324', '#fffac8', '#800000', '#aaffc3', '#808000', '#ffd8b1', '#000075', '#808080', '#ffffff', '#000000')
    

    你可以试试!

    【讨论】:

    • 这并不能真正回答问题,即生成n 独特的颜色,而不是一组定义的颜色。尝试更新您的答案
    【解决方案8】:

    你可以像这样生成一组颜色:

    myCol = c("pink1", "violet", "mediumpurple1", "slateblue1", "purple", "purple3",
              "turquoise2", "skyblue", "steelblue", "blue2", "navyblue",
              "orange", "tomato", "coral2", "palevioletred", "violetred", "red2",
              "springgreen2", "yellowgreen", "palegreen4",
              "wheat2", "tan", "tan2", "tan3", "brown",
              "grey70", "grey50", "grey30")
    

    这些颜色尽可能不同。对于那些相似的颜色,它们会形成渐变,以便您轻松分辨它们之间的差异。

    【讨论】:

      【解决方案9】:

      在我的理解中,搜索独特的颜色与从单位立方体中有效搜索有关,其中立方体的 3 个维度是沿红色、绿色和蓝色轴的三个向量。这可以简化为在圆柱体中搜索(HSV 类比),您可以在其中固定饱和度 (S) 和值 (V) 并找到随机色调值。它在许多情况下都有效,请在此处查看:

      https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/

      在 R 中,

      get_distinct_hues <- function(ncolor,s=0.5,v=0.95,seed=40) {
        golden_ratio_conjugate <- 0.618033988749895
        set.seed(seed)
        h <- runif(1)
        H <- vector("numeric",ncolor)
        for(i in seq_len(ncolor)) {
          h <- (h + golden_ratio_conjugate) %% 1
          H[i] <- h
        }
        hsv(H,s=s,v=v)
      }
      

      另一种方法是“统一”使用 R 包 https://cran.r-project.org/web/packages/uniformly/index.html

      而这个简单的函数可以生成与众不同的颜色:

      get_random_distinct_colors <- function(ncolor,seed = 100) {
        require(uniformly)
        set.seed(seed)
        rgb_mat <- runif_in_cube(n=ncolor,d=3,O=rep(0.5,3),r=0.5)
        rgb(r=rgb_mat[,1],g=rgb_mat[,2],b=rgb_mat[,3])
      }
      

      可以通过grid-search想出更多涉及的功能:

      get_random_grid_colors <- function(ncolor,seed = 100) {
        require(uniformly)
        set.seed(seed)
        ngrid <- ceiling(ncolor^(1/3))
        x <- seq(0,1,length=ngrid+1)[1:ngrid]
        dx <- (x[2] - x[1])/2
        x <- x + dx
        origins <- expand.grid(x,x,x)
        nbox <- nrow(origins) 
        RGB <- vector("numeric",nbox)
        for(i in seq_len(nbox)) {
          rgb <- runif_in_cube(n=1,d=3,O=as.numeric(origins[i,]),r=dx)
          RGB[i] <- rgb(rgb[1,1],rgb[1,2],rgb[1,3])
        }
        index <- sample(seq(1,nbox),ncolor)
        RGB[index]
      } 
      

      通过以下方式检查此功能:

      ncolor <- 20
      barplot(rep(1,ncolor),col=get_distinct_hues(ncolor))          # approach 1
      barplot(rep(1,ncolor),col=get_random_distinct_colors(ncolor)) # approach 2
      barplot(rep(1,ncolor),col=get_random_grid_colors(ncolor))     # approach 3
      

      但是,请注意,用人类可感知的颜色定义一个独特的调色板并不简单。上述哪种方法会产生不同的颜色集还有待测试。

      【讨论】:

        【解决方案10】:

        您可以为此目的使用 Polychrome 包。它只需要颜色的数量和一些seedcolors。例如:

        # install.packages("Polychrome")
        library(Polychrome)
        
        # create your own color palette based on `seedcolors`
        P36 = createPalette(36,  c("#ff0000", "#00ff00", "#0000ff"))
        swatch(P36)
        

        您可以在https://www.jstatsoft.org/article/view/v090c01 了解有关此软件包的更多信息。

        【讨论】:

          猜你喜欢
          • 2018-10-23
          • 2010-10-20
          • 2010-11-13
          • 2011-03-09
          • 2021-09-13
          • 2021-11-23
          • 2021-10-21
          • 2018-05-24
          相关资源
          最近更新 更多