Here is the reproducible data that I'm using as an example.
Name <- c("Blueberry", "Raspberry", "Celery", "Apples", "Peppers")
Class <- c("Berries", "Berries", "Vegetable", "Fruit", "Vegetable")
Yield <- c(30, 20, 15, 25, 40)
example <- data.frame(Class = Class, Name = Name, Yield = Yield)
When plotted with ggplot2
we get ...
ggplot(example, aes(x = Name, y = Yield, fill = Name))+
geom_bar(stat = "identity")
It would be helpful if we could give fills of similar colour to those that have the same class. For example, if Vegetables were shades of blue, Berries were shades of pink, and Fruits were shades of green you could see the yield by class of plants but still visually see the name (which is more important to us)
I feel that I could accomplish this with scale_fill_hue()
but I can't seem to get it to work
ggplot(example, aes(x = Name, y = Yield))+
geom_bar(aes(fill = Class),stat = "identity")+
scale_fill_hue("Name")
The basic design in ggplot
is one scale per aes
thetic (see @hadley's opinion e.g. here). Thus, work-arounds are necessary in a case like yours. Here is one possibility where fill
colors are generated outside ggplot
. I use color palettes provided by package RColorBrewer
. You can easily check the different palettes here. dplyr
functions are used for the actual data massage. The generated colours are then used in scale_fill_manual
:
library(dplyr)
library(RColorBrewer)
# create look-up table with a palette name for each Class
pal_df <- data.frame(Class = c("Berries", "Fruit", "Vegetable"),
pal = c("RdPu", "Greens", "Blues"))
# generate one colour palette for each Class
df <- example %>%
group_by(Class) %>%
summarise(n = n_distinct(Name)) %>%
left_join(y = pal_df, by = "Class") %>%
rowwise() %>%
do(data.frame(., cols = colorRampPalette(brewer.pal(n = 3, name = .$pal))(.$n)))
# add colours to original data
df2 <- example %>%
arrange(as.integer(as.factor(Class))) %>%
cbind(select(df, cols)) %>%
mutate(Name = factor(Name, levels = Name))
# use colours in scale_fill_manual
ggplot(data = df2, aes(x = Name, y = Yield, fill = Name))+
geom_bar(stat = "identity") +
scale_fill_manual(values = df2$cols)
A possible extension would be to create separate legends for each 'Class scale'. See e.g. my previous attempts here (second example) and here.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments