开发者

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")

Changing the order of dodged bars in ggplot2 barplot

incorrect order in dodge:

g+geom_bar(stat="identity",position="dodge")

Changing the order of dodged bars in ggplot2 barplot

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!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜