Cecilia López
Cecilia López

Reputation: 357

R - Keep the same color for each group in different boxplots

Long time reader first time poster, sorry in advance for any mistakes.

I have a dataset with several factors and I wolud like to asign a color for each factor in such way that when I plot a subgroup of factors the colors keep constant.

I can give a simple example.

# Generating a random dataset
df <- data.frame(values = runif(20, min=0, max=10), groups = rep(c("A","B","C","D"), each = 5))
df$groups <- as.factor(df$groups)

df

values groups
1  9.3959013      A
2  6.0607064      A
3  3.3956529      A
4  7.9427183      A
5  9.4938858      A
6  4.4047519      B
7  0.7775106      B
8  2.0356925      B
9  6.9077875      B
10 3.8141609      B
11 2.6100288      C
12 8.5189150      C
13 3.5696664      C
14 7.8106244      C
15 7.2489862      C
16 6.4197579      D
17 6.4479676      D
18 8.9319776      D
19 2.0124674      D
20 5.2652708      D

When I plot each group I want to asign "red" to A, "yellow" to B and so on:

ggplot(df, aes(x=groups, y=values, fill=groups))+
geom_boxplot()+
scale_fill_manual(values=c("red", "yellow", "green", "blue"))

plot 1

Now, if I only want to plot A, C and D, I'd like for A to keep being red, C green and D blue

ggplot(df[!df$groups=="B",], aes(x=groups, y=values, fill=groups))+
geom_boxplot()+
scale_fill_manual(values=c("red", "green", "blue"))

plot 2

Or if I only plot C and D, I'd like them to keep being green and blue.

I don't usually asign colors manually, y use a predesigned color palette such as viridis, but if I use scale_fill_viridis the first group shown in the boxplot will always be purple, and the last, yellow.

I've thought of creating a palette asigning a color for each factor:

palette <- data.frame(factors= levels(df$groups),  colors= viridis_pal() 
(length(levels(df$groups))))

palette

factors    colors
1       A #440154FF
2       B #31688EFF
3       C #35B779FF
4       D #FDE725FF

But I don't know how to integrate this into ggplot.

Many thanks!

Upvotes: 1

Views: 1204

Answers (1)

stefan
stefan

Reputation: 125028

You could convert the df with the colors to a named vector via tibble::deframe which can then be passed to scale_fill_manual like so:

library(ggplot2)

set.seed(42)

df <- data.frame(values = runif(20, min=0, max=10), groups = rep(c("A","B","C","D"), each = 5))
df$groups <- as.factor(df$groups)

palette <- data.frame(factors = levels(df$groups),  colors= scales::viridis_pal()(length(levels(df$groups))))
palette <- tibble::deframe(palette)

ggplot(df, aes(x=groups, y=values, fill=groups))+
  geom_boxplot()+
  scale_fill_manual(values = palette) 

enter image description here

Upvotes: 0

Related Questions