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")
Changing the order of legend labels can be achieved by reordering the factor levels of the Species variable mapped to the color aesthetic.
You can use the following syntax to change the legend labels in ggplot2: p + scale_fill_discrete(labels=c('label1', 'label2', 'label3', ...))
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.
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.
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)
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"))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With