How to scale colour in ggplot for independent laye

2019-07-04 07:49发布

I have a data set that documents the energy use of three buildings. I have a melted data frame that can be mimicked from the diamonds set:

data <- melt(diamonds[,c('depth','table','cut','color')],id=c('cut','color'))

Essentially, I have heating ('depth') and cooling ('table') data for each month('cut') from three different buildings (7 'color' factors). I would like to plot the three buildings (7 'color' factors) side by side in a bar plot for each month ('cut').

I want the bars representing either cooling ('table') or heating ('depth') to vary their shade based on the building ('color' factor) while remaining grouped by month ('cut'). This is a bad way to visualize the diamonds data, but should work well for buildings as their heating and cooling months typically don't overlap. So far I have:

p <- ggplot(data,
        aes(color,value,group=cut))
p <- p + geom_bar(stat = 'identity',
              position = 'dodge',
              aes(fill = variable))
print(p)

I tried playing with scale_fill_manual, but couldn't think of a strategy that works:

colours <- c('#0000FF', '#0033FF', '#0066FF', '#FF0000', '#FF3300', '#FF6600')

p <- p + scale_fill_manual(values = colours,
                           group = data$variable)

标签: r scale ggplot2
1条回答
Animai°情兽
2楼-- · 2019-07-04 08:26

With some trickery, it is possible. Deriving a data set based on diamonds was very good, but I want to work with a smaller data set

set.seed(1234)
data <-
expand.grid(month = month.abb,
            building = c("Building A", "Building B", "Building C"),
            hc = c("Heating", "Cooling"))
data$value <- rnorm(nrow(data), 60, 10)

You want your fill colour to be based both on the variable (hc) and the building (building), so set it to that interaction.

ggplot(data, aes(building,value,group=month)) + 
  geom_bar(stat = 'identity',
           position = 'dodge',
           aes(fill = interaction(building, hc)))

enter image description here

We can pick colors that represent different near shades to make these more like what you want. I used the middle of the "Blues" and "Reds" of the RColorBrewer palettes.

colours <- c("#FC9272", "#FB6A4A", "#EF3B2C", "#9ECAE1", "#6BAED6", "#4292C6")
# library("RColorBrewer")
# colours <- c(brewer.pal(9,"Reds")[4:6], brewer.pal(9,"Blues")[4:6])

and used scale_fill_manual to assign these colours.

ggplot(data, aes(building,value,group=month)) + 
  geom_bar(stat = 'identity',
           position = 'dodge',
           aes(fill = interaction(building, hc))) +
  scale_fill_manual(values=colours)

enter image description here

The real trickery is in making the legend less convoluted. I just list 2 of the levels (the middle building in terms of color) and give them different names (and a different title for the legend).

ggplot(data, aes(building,value,group=month)) + 
  geom_bar(stat = 'identity',
           position = 'dodge',
           aes(fill = interaction(building, hc))) +
  scale_fill_manual("Heating/cooling",
                    values=colours,
                    breaks=c("Building B.Heating", "Building B.Cooling"),
                    labels=c("Heating", "Cooling"))

enter image description here

查看更多
登录 后发表回答