Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reorder a legend in ggplot2?

Tags:

r

ggplot2

Given a two column data frame with a categorical column of labels and a quantitative column of percent data, I can reliably produce a bar chart in ggplot that sorts the bars by value rather than by alphabetical order using the following:

ggplot(data=df, aes(x=reorder(Label, Percent), y=Percent, fill=Label)) + geom_bar()

This tells reorder to sorts the bar chart by the percent value rather than the text, making it easier to see the changes.

I cannot, however, get the legend to match: instead it persists in being sorted by the original alphabetical values. This results in a legend which doesn't match the chart, which is confusing.

I've looked on StackOverflow and elsewhere, and haven't found a fix that will work. Any advice?

Edit: per requests, this is essentially the data:

Labels <- c("G", "G", "A", "C", "M", "B", "M", "G", "A","M")
Percent <- c("-0.241","-0.046", "-0.037", "-0.024", "-0.003","0.007","0.01","0.059","0.121", "0.152")
like image 679
sogrady Avatar asked Nov 11 '14 19:11

sogrady


People also ask

How do I reorder legend labels in R?

Changing the order of legend labels can be achieved by reordering the factor levels of the Species variable mapped to the color aesthetic.

How do I change the legend label in ggplot2?

You can use the following syntax to change the legend labels in ggplot2: p + scale_fill_discrete(labels=c('label1', 'label2', 'label3', ...))

How do I get rid of the legend in ggplot2?

Example 1: Remove All Legends in ggplot2 We simply had to specify legend. position = “none” within the theme options to get rid of both legends.


2 Answers

I find the easiest way is to just reorder your data before plotting. By specifying the reorder(() inside aes(), you essentially making a ordered copy of it for the plotting parts, but it's tricky internally for ggplot to pass that around, e.g. to the legend making functions.

This should work just fine:

df$Label  <- with(df, reorder(Label, Percent))
ggplot(data=df, aes(x=Label, y=Percent, fill=Label)) + geom_bar()

I do assume your Percent column is numeric, not factor or character. This isn't clear from your question. In the future, if you post dput(df) the classes will be unambiguous, as well as allowing people to copy/paste your data into R.

like image 199
Gregor Thomas Avatar answered Oct 05 '22 02:10

Gregor Thomas


With the data you provided, the following works for me basically applying the suggestion from Frank:

Labels <- c("G", "G", "A", "C", "M", "B", "M", "G", "A","M")
Percent <- c("-0.241","-0.046", "-0.037", "-0.024", "-0.003","0.007","0.01","0.059","0.121", "0.152")
df <- data.frame(Labels, Percent)
df$Percent <- as.numeric(as.character(df$Percent))
legend_ord <- levels(with(df, reorder(Labels, Percent)))

library(ggplot2)
p <- ggplot(data=df, aes(x=reorder(Labels, Percent), y = Percent, fill=Labels)) 
p <- p + geom_bar(stat="identity")
p + scale_fill_discrete(breaks=legend_ord)

enter image description here

Regarding your followup question, if you have specific colors you can assign them within the scale_fill_manual call.

p <- ggplot(data=df, aes(x=reorder(Labels, Percent), y = Percent, fill=Labels)) 
p <- p + geom_bar(stat="identity")
p + scale_fill_manual(breaks=legend_ord, 
    values=c("G"="#0000FF", "C"="#003FBF","B"="#007F7F","A"="#00BF3F","M"="#00FF00"))

enter image description here

like image 45
cdeterman Avatar answered Oct 05 '22 02:10

cdeterman