Changing the order of dodged bars in ggplot2 barplot
I have a dataframe df.all
and I'm plotting it in a bar plot with ggplot2 using the code below. I'd like to make it so that the order of the dodged bars is flipped. That is, so that the bars labeled "Singular" come before the bars labeled "Plural".
ggplot(df.all, aes(gram, V1, fill=number)) +
geom_bar(stat="identity", position="dodge") +
scale_x_discrete(labels=c("Grammatical","Ungrammatical")) +
scale_y_continuous(formatter="percent", limits=c(0,1)) +
facet_grid(. ~ experiment) +
scale_fill_hue("Attractor", breaks=c("S","P"), labels=c("Singular","Plural"))
I've tried doing levels(df.all$number) = c("S", "P")
thinking that maybe ggplot uses the order of the levels to decide plotting order, but that didn't work. I'm not sure what else to try. Any ideas?
The contents of df.all
, in case it's useful:
> df.all
number gram experiment V1
1 S G BERIMBAU_AGR_A 0.8133333开发者_如何转开发
2 S G BERIMBAU_AGR_B 0.8658537
3 S U BERIMBAU_AGR_A 0.5436242
4 S U BERIMBAU_AGR_B 0.4597701
5 P G BERIMBAU_AGR_A 0.8580645
6 P G BERIMBAU_AGR_B 0.8536585
7 P U BERIMBAU_AGR_A 0.3087248
8 P U BERIMBAU_AGR_B 0.3975904
> str(df.all)
'data.frame': 8 obs. of 4 variables:
$ number : Factor w/ 2 levels "S","P": 2 2 2 2 1 1 1 1
..- attr(*, "scores")= num [1:2(1d)] 0 -1
.. ..- attr(*, "dimnames")=List of 1
.. .. ..$ : chr "P" "S"
$ gram : Factor w/ 2 levels "G","U": 1 1 2 2 1 1 2 2
$ experiment: Factor w/ 4 levels "BERIMBAU_AGR_A",..: 1 4 1 4 1 4 1 4
$ V1 : num 0.813 0.866 0.544 0.46 0.858 ...
I think df.all$number
needs to be an ordered factor. Try df.all$number <- ordered(df.all$number)
In some cases I don't think this is possible:
layerCake<-data.frame(group=c(rep("normal",4),rep("tumor",4)),
class=factor(rep(c("exon","intron","intergenic","unmapped"),2),levels=rev(c("exon","intron","intergenic","unmapped")),ordered=TRUE),
fraction=c(.02,.25,.50,.23,.015,.20,.555,.23)
)
layerCake[layerCake$group=='normal',"reads"]<-130948403*layerCake[layerCake$group=='normal',"fraction"]
layerCake[layerCake$group=='tumor',"reads"]<-200948403*layerCake[layerCake$group=='tumor',"fraction"]
g<-ggplot(layerCake, aes(x=factor(group),y=reads, fill=factor(class),order = as.numeric(class)))+xlab("Group")+scale_fill_discrete(name="Anno Class",breaks=c("exon","intron","intergenic","unmapped"))
correct order in stacked:
g+geom_bar(stat="identity",position="stack")
incorrect order in dodge:
g+geom_bar(stat="identity",position="dodge")
let's try to reverse the order in ggplot:
g<-ggplot(lc, aes(x=factor(group),y=reads, fill=factor(class),order = -as.numeric(class)))+xlab("Group")+scale_fill_discrete(name="Anno Class",breaks=c("exon","intron","intergenic","unmapped"))
g+geom_bar(stat="identity",position="dodge")
no dice
let's try to reorder the data frame
lc <- with(lc, lc[order(-as.numeric(class)), ])
g<-ggplot(lc, aes(x=factor(group),y=reads, fill=factor(class),order = -as.numeric(class)))+xlab("Group")+scale_fill_discrete(name="Anno Class",breaks=c("exon","intron","intergenic","unmapped"))
g+geom_bar(stat="identity",position="dodge")
nope
Hadley has provided a solution. Here's a replication of the problem and the solution.
The goal is to get the bars labeled "S" to come before the bars labeled "P". This doesn't happen by default because R orders levels alphabetically.
df <- read.csv("http://pealco.net/code/ggplot_dodge/df.txt")
ggplot(df, aes(gram, V1, fill=number))
+ geom_bar(stat="identity", position="dodge")
As Hadley commented in another answer, "you need to reorder based on the x variables, not the y variable". Though I'm not sure why this works.
To flip the order of the factors in this example, you can convert the factor to numeric and multiply by -1.
df <- with(df, df[order(gram, -as.numeric(number)), ])
I'd still like some more explanation about why df <- with(df, df[order(gram, -as.numeric(number)), ])
works.
Changing factor levels really does change the order of dodged bars! Common pitfall: the colors still stay at a certain position, so taking a quick glance makes it look like the order has not changed. But if you look at the values you will see that the order really has changed.
Edit: My previous answer below only changes order of color scheme given to bars. This is still useful, as we may often want to reverse the color scheme at the same time as changing the order of the bars:
I was using scale_fill_manual because I wanted to manually fill the colors of my bars.
ggplot(data, aes_string(x = "countries", y = "population", fill = "agegroups")) +
scale_fill_manual(values = CustomColorFunction(), limits = (levels(data$agegroups)))
Spent 5 hours tinkering with changing factor levels and arranging the dataframe hopes this helps someone!
精彩评论