2
votes

I have a dataframe which has a set of manufacturers and collected data for those manufacturers. The list of manufacturers and/or the attribute data can change, depending on the run. I display this as a line chart in ggplot, but what I want is to have the legend order match the 'up/down' order of the final year of data. So for this chart: Default Legend Order

I'd like to see the legend order (and color) be Yoyodyne (purple), Widget (green), Wonka (blue) and Acme (red). I can't (or don't think I can) use scale_color_manual as the data-in from one model run to the next the end-order (in 2032) may differ and/or the list of manufacturers may differ.

Code for doing chart is (last part, pz, just to simplify x axis display):

px <- ggplot(bym, aes(x=Model.Year, y=AverageCost, colour=Manufacturer))
py <- px + ggtitle("MyChart") + labs(x="Year", y="Foo") + geom_line(size=0.5) + geom_point()
pz <- py + scale_x_continuous(breaks=c(min(bym$Model.Year),max(bym$Model.Year)))
pz
2

2 Answers

2
votes

You can set the order of the legend objects by using dplyr::mutate function in conjunction with the factor function. To set the colors in the order you want, you can just create a vector with your desired colors in the order you want them and pass them to scale_color_manual. I have done this in the example below. Mine looks a little different then yours because I removed the intermediate assignments.

bym <- data.frame(
  Model.Year = rep(seq(2016, 2030, 1), 4),
  AverageCost = rnorm(60),
  Manufacturer = rep(c("Yoyodyne", "Widget", "Wonka", "Acme"), each = 15)
)

my_colors <- c("purple", "green",  "blue", "red")

bym %>%
  mutate(Manufacturer = factor(Manufacturer, 
                               levels = c("Yoyodyne", "Widget", "Wonka",     "Acme"))) %>%
  ggplot(aes(x=Model.Year, y=AverageCost, colour=Manufacturer)) +
  ggtitle("MyChart") + 
  labs(x="Year", y="Foo") + 
  geom_line(size=0.5) + 
  geom_point()+ 
  scale_x_continuous(breaks=c(min(bym$Model.Year),max(bym$Model.Year))) +
  scale_color_manual(values = my_colors)
2
votes

Have you tried setting the levels for Manufacturer according to the last year? For example, you can add a column with levels set this way:

# order Manufacturer by AverageCost in the last year
colours = bym[with(bym[bym$Model.Year == 2032,], order(-AverageCost)),]$Manufacturer
# add factor with levels ordered by colours
bym$Colour = factor(bym$Manufacturer, levels=as.character(colours))

Then use Colour for your colour aesthetic.

EDIT: That is, if you want to stick to base R. The answer with dplyr::mutate is much easier to use.