Reputation: 43
I want to plot some data of individuals who belong to groups.
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()
The easy, first step is to assign each individual in z a different color.
However, ideally, I would then additionally be able to group the individuals according to z2 such that e.g. every individual in group 1 has a individual color in the red spectrum and every individual in group 2 has an individual color in the blue spectrum (and so on).
Is there a way to programmatically do this?
Upvotes: 4
Views: 1018
Reputation: 23717
This is a slight modification of @LAPs answer in order to also adjust for the numbers of different "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))
The advantage is that it uses single color palettes - depending on how many colors you have, you can and should also think about color blind and printer safe colors. Have a look at http://colorbrewer2.org, this is a great site and it tells you also the names of the palettes to use :)
Upvotes: 2
Reputation: 6685
This solution is only scalable for the amount of different colors you need per group, not for the number of groups you have (so only two groups):
First we extract the number of unique values for z
:
colornumbers <- sapply(split(df, df$z2), function(x) length(unique(x$z)))
> colornumbers
1 2
5 5
Then we create a vector of color samples from two different color palettes (install packages grDevices
and 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"
Now we plot with a 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)
This solution also requires the two groups to be sorted value-wise, so I'm not sure how applicable it would be in a real data scenario.
Upvotes: 2