Я хочу изобразить некоторые данные лиц, принадлежащих к группам.

library(dplyr)
library(ggplot2)

x <- rep(1:10, 10)
y <- c(1:10, 2:11, 3:12, 4:13, 5:14, 6:15, 7:16, 8:17, 9:18, 10:19)
z <- c(rep(1, 10), rep(2, 10), rep(3, 10), rep(4, 10), rep(5, 10), rep(6, 10), rep(7, 10), rep(8, 10), rep(9, 10), rep(10, 10)) %>%
  as.factor()
z2 <- c(rep(1, 50), rep(2, 50))


tibble(x, y, z, z2) %>%
  ggplot(aes(x = x,
             y = y,
             color = z)) +
  geom_line()

Первый простой шаг - назначить каждому цвету z свой цвет.
Однако в идеале я мог бы дополнительно сгруппировать людей в соответствии с z2 , например, каждый человек в группе 1 имеет индивидуальный цвет в красном спектре, а каждый человек в группе 2 имеет индивидуальный цвет в синем спектре (и так далее).
Есть ли способ сделать это программно?

4
CHarris 13 Сен 2018 в 11:56

2 ответа

Лучший ответ

Это решение масштабируется только для количества разных цветов, которое вам нужно для каждой группы, а не для количества групп, которые у вас есть (так что только две группы):

Сначала мы извлекаем количество уникальных значений для z:

colornumbers <- sapply(split(df, df$z2), function(x) length(unique(x$z)))
> colornumbers
1 2 
5 5 

Затем мы создаем вектор цветовых образцов из двух разных цветовых палитр (устанавливаем пакеты grDevices и colorRamps):

mycolors <- as.vector(mapply(function(x, y){
  x(y)
}, list(grDevices::heat.colors, colorRamps::blue2green), colornumbers))

> mycolors
 [1] "#FF0000FF" "#FF5500FF" "#FFAA00FF" "#FFFF00FF" "#FFFF80FF" "#0000FF"   "#0040BF"   "#008080"   "#00BF40"   "#00FF00"  

Теперь строим с scale_color_manual:

tibble(x, y, z, z2) %>%
  ggplot(aes(x = x,
             y = y,
             color = z)) +
  geom_line() + 
  scale_color_manual(breaks = z, values = mycolors)

enter image description here

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

2
LAP 13 Сен 2018 в 10:04

Это небольшая модификация ответа @LAP, чтобы также отрегулировать количество различных "z2"

library(RColorBrewer)
my_dat <- tibble(x, y, z, z2)
n_col = length(unique(my_dat$z2)) #get the numbers of z2
colornumbers <- sapply(split(my_dat, my_dat$z2), function(x) length(unique(x$z))) #Thanks @LAP

  sequential_pal <- c('Blues', 'BuGn', 'BuPu', 'GnBu', 'Greens', 'Greys', 'Oranges', 'OrRd', 'PuBu', 'PuBuGn', 'PuRd', 'Purples', 'RdPu', 'Reds', 'YlGn', 'YlGnBu', 'YlOrBr', 'YlOrRd')
# that is the vector containing the sequential color brewer palettes - hopefully they should be sufficient... 
  set.seed(1)
  n_seq_pal <- sample(sequential_pal, size = n_col) # gets the correct numbers
#  this could certainly be tweaked by selecting those that lie most distant apart. 
# or just randomly try to change set.seed ;)

mycolors <- 
  as.vector(mapply(brewer.pal, colornumbers, n_seq_pal)) # slight modification of @LAP s code

ggplot() +
  geom_line(data = my_dat, aes(x = x, y = y, color = z)) +
  scale_color_manual(breaks = z, values = as.vector(mycolors))

enter image description here

Преимущество состоит в том, что он использует одноцветные палитры - в зависимости от того, сколько цветов у вас есть, вы также можете и должны думать о цветах для слепых и безопасных для принтера цветах. Взгляните на http://colorbrewer2.org, это отличный сайт, и на нем также указаны названия палитры для использования :)

2
Tjebo 13 Сен 2018 в 11:28