Как сгенерировать ряд наиболее отличительных цветов в R?


131

Я рисую категориальный набор данных и хочу использовать отличительные цвета для представления разных категорий. Учитывая число n, как я могу получить nколичество САМЫХ отличительных цветов в R? Спасибо.



Ответы:


108

Соединил все качественные палитры из 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))

colour_Brewer_qual_60

Другое решение: взять все цвета R с графических устройств и взять с них образцы. Я удалил оттенки серого, так как они слишком похожи. Это дает 433 цвета

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

набор из 20 цветов

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

с 200 цветами n = 200:

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

набор из 200 цветов


Есть ли возможность преобразовать шестнадцатеричные коды в colсоответствующие названия цветов?
Prradep

@Prradep, что colты имеешь в виду? colorот графических устройств имеет название. Если вы имеете в виду в целом, не все шестнадцатеричные коды имеют соответствующие названия цветов (в них всего 433 цвета, grDevicesно гораздо больше шестнадцатеричных кодов)
Елена Чуклина

Я упоминаю об col=sample(col_vector, n)из RColorBrewerпакета в вашем фрагменте кода. Например, как найти названия цветов для #B3E2CD, #E78AC3, #B3DE69доступных из sample(col_vector,3). Или как найти все шестнадцатеричные коды, заданные brewer.palфункцией, с их названиями цветов.
Prradep

2
@Prradep, поскольку RColorBrewerпалитры не являются производными от grDevicesцветов, которым присвоены имена, а представляют собой просто шестнадцатеричные коды, насколько мне известно, вы не можете сделать это с RColorBrewerпалитрами, даже с качественными.
JelenaČuklina

1
@ytu то цвета не различимы. Если это абсолютно необходимо, я бы посоветовал поискать «создание градиента» в R, а затем использовать рандомизированную выборку цветов. Но сопоставление цветов с факторами не сработает, человеческое восприятие может обрабатывать, может быть, 20-40 цветов, остальное не сильно отличается.
JelenaČuklina

70

Вот несколько вариантов:

  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. Посмотрите на colorBrewerпакет (и на сайт ). Если вы хотите расходящиеся цвета, то выберите на сайте расходящиеся . Например,

     library(colorBrewer)
     brewer.pal(7, "BrBG")
  4. На веб-сайте « Я хочу оттенок» есть много хороших палитр. Опять же, просто выберите ту палитру, которая вам нужна. Например, вы можете получить с сайта цвета 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)))

спасибо за Ваш ответ. Он генерирует цвета, но некоторые из них не очень отличаются друг от друга. возможно, мне следовало больше подчеркнуть это в своих вопросах.
RNA

1
@RNAer Я обновил свой ответ. Вы можете использовать предложения 3 и 4, чтобы получить расходящиеся палитры.
csgillespie 07

1
I want hueотличный сайт. Это именно то, что я хочу. Учитывая число, как создать палитру из числа цветов. но можем ли мы сделать это в R автоматически?
RNA

Это превосходно. Однако за этим веб-сайтом стоит много оборудования. Не думаю, что это будет тривиально переделывать. Было бы неплохо, если бы у i want hueнего был API, который позволял бы автоматически запрашивать его (возможно, это так - я не долго искал)
Бен Болкер,

8
@BenBolker - Я сделал суть для версии R из i want hue, здесь . Эффективность можно повысить (например, за счет сохранения образцов цвета как объектов данных), но общая идея есть. (Загрузить с devtools::source_gist('45b49da5e260a9fc1cd7'))
jbaums

36

Вы также можете попробовать randomcoloRпакет :

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)

введите описание изображения здесь


3
Спасибо. Мне пришлось использовать unname(distinctColorPalette(n))для работы с ggplot. Думаю, ggplot нужен безымянный вектор. col_vector <- unname(distinctColorPalette(n))а затем... + scale_color_manual(values=col_vector) ...
Gaurav

19

Не ответ на вопрос OP, но стоит упомянуть, что есть viridisпакет, который имеет хорошие цветовые палитры для последовательных данных. Они одинаково воспринимаются, безопасны для дальтоников и подходят для печати.

Чтобы получить палитру, просто установите пакет и воспользуйтесь функцией viridis_pal(). Есть четыре варианта «A», «B», «C» и «D» на выбор.

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

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

Также есть отличный доклад, объясняющий сложность хороших цветовых карт на YouTube:

Лучшая цветовая карта по умолчанию для Matplotlib | SciPy 2015 | Натаниэль Смит и Стефан ван дер Уолт


17
Это не очень подходит для отличительных цветов.
Кристофер Джон

14

Вы можете использовать colorRampPaletteиз базы или RColorBrewerпакета:

С помощью 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пакете другие доступные палитры. Надеюсь это поможет.


1
Спасибо. Мне нравится последний вариант brewer.pal. но он ограничен 9 цветами. На самом деле у меня более 9 категорий. Первые альтернативы генерируют цвета градиента, которые не так различимы, как мне хотелось бы.
RNA

2
вы не сможете выбрать много «различных» цветов. Полагаю, вы можете получить максимум 12. Вы должны проверить colorbrewer2.org и получить цвета (если я прав, есть палитра из 12 цветов).
Arun

Будет сложно найти более 12 отличительных колоутов - я думаю, это обсуждается на странице
colorbrewer

это нормально, пока они являются «наиболее» отличительными из доступных цветов, даже они становятся менее различимыми с ростом числа.
RNA

3
Если ваша проблема заключается в том, что похожие цвета расположены рядом друг с другом при назначении смежным категориям (как и палитра радуги), то вы можете просто рандомизировать вывод радуги, используя что-то вроде: радуга (n = 10) [образец (10)]
Дэвид Робертс

12

Я бы рекомендовал использовать внешний источник для больших цветовых палитр.

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

есть услуга составления палитры любого размера по различным параметрам и

/graphicdesign/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")

3

Я нашел веб-сайт, предлагающий список из 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')

Вы можете попробовать!


1
Это на самом деле не отвечает на вопрос о создании n отличительных цветов, а не о наборе определенных цветов. Попробуйте обновить свой ответ
Михал

1

Вы можете создать такой набор цветов:

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")

Эти цвета максимально различимы. Для этих похожих цветов они образуют градиент, чтобы вы могли легко отличить их.


0

В моем понимании поиск отличительных цветов связан с эффективным поиском из единичного куба, где 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])
}

Можно придумать немного более сложную функцию с помощью поиска по сетке:

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

Однако обратите внимание, что определить отдельную палитру цветов, воспринимаемых человеком, непросто. Какой из вышеперечисленных подходов генерирует разнообразный набор цветов, еще предстоит проверить.


0

Для этого можно использовать пакет 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 .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.