2

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

Graph

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

Class

user3900661
  • 133
  • 1
  • 9

2 Answers2

2

The basic design in ggplot is one scale per aesthetic (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)

enter image description here

A possible extension would be to create separate legends for each 'Class scale'. See e.g. my previous attempts here (second example) and here.

Community
  • 1
  • 1
Henrik
  • 65,555
  • 14
  • 143
  • 159
0

You can use an alpha scale as a quick (albeit not perfect) way to change intensities of colour within a class:

library("ggplot2"); theme_set(theme_bw())
library("plyr")
## reorder
example <- mutate(example,
               Name=factor(Name,levels=Name))
example <- ddply(example,"Class",transform,n=seq_along(Name))
g0 <- ggplot(example, aes(x = Name, y = Yield))
g0 + geom_bar(aes(fill = Class,alpha=factor(n)),stat = "identity")+
    scale_alpha_discrete(guide=FALSE,range=c(0.5,1))
Ben Bolker
  • 211,554
  • 25
  • 370
  • 453