grouped barplot: order x-axis & keep constant bar width, in case of missing levels

亡梦爱人 提交于 2019-12-20 03:19:23

问题


Here is my script (example inspired from here and using the reorder option from here):

library(ggplot2)
Animals <- read.table(
  header=TRUE, text='Category        Reason Species
1   Decline       Genuine      24
2  Improved       Genuine      16
3  Improved Misclassified      85
4   Decline Misclassified      41
5   Decline     Taxonomic       2
6  Improved     Taxonomic       7
7   Decline       Unclear      10
8  Improved       Unclear     25
9  Improved           Bla     10
10  Decline         Hello     30')

fig <- ggplot(Animals, aes(x=reorder(Animals$Reason, -Animals$Species), y=Species, fill = Category)) + 
  geom_bar(stat="identity", position = "dodge")

This gives the following output plot:

What I would like is to order my barplot only on condition 'Decline', and all the 'Improved' would not be inserted in the middle. Here is what I would like to get (after some svg editing):

So now all the whole 'Decline' condition is sorted and the 'Improved' condition comes after. Besides, ideally, the bars would all be at the same width, even if the condition is not represented for the value (e.g. "Bla" has no "Decline" value).

Any idea on how I could do that without having to play with SVG editors? Many thanks!


回答1:


First let's fill your data.frame with missing combinations like this.

library(dplyr)
Animals2 <- expand.grid(Category=unique(Animals$Category), Reason=unique(Animals$Reason)) %>% data.frame %>% left_join(Animals)

Then you can create an ordering variable for the x-scale:

myorder <- Animals2 %>% filter(Category=="Decline") %>% arrange(desc(Species)) %>% .$Reason %>% as.character

An then plot:

ggplot(Animals2, aes(x=Reason, y=Species, fill = Category)) + 
  geom_bar(stat="identity", position = "dodge") + scale_x_discrete(limits=myorder)




回答2:


Define new data frame with all combinations of "Category" and "Reason", merge with data of "Species" from data frame "Animals". Adapt ggplot by correct scale_x_discrete:

Animals3 <-  expand.grid(Category=unique(Animals$Category),Reason=unique(Animals$Reason))
Animals3 <- merge(Animals3,Animals,by=c("Category","Reason"),all.x=TRUE)
Animals3[is.na(Animals3)] <- 0
Animals3 <- Animals3[order(Animals3$Category,-Animals3$Species),]
ggplot(Animals3, aes(x=Animals3$Reason, y=Species, fill = Category)) + geom_bar(stat="identity", position = "dodge") + scale_x_discrete(limits=as.character(Animals3[Animals3$Category=="Decline","Reason"]))



回答3:


To achieve something like that I would adjust the data frame when working with ggplot. Add the missing categories with a value of zero.

Animals <- rbind(Animals, 
                 data.frame(Category = c("Improved", "Decline"), 
                            Reason = c("Hello", "Bla"), 
                            Species = c(0,0)
                            )
)



回答4:


Along the same lines as the answer from user Alex, a less manual way of adding the categories might be

d <- with(Animals, expand.grid(unique(Category), unique(Reason)))
names(d) <- names(Animals)[1:2]
Animals <- merge(d, Animals, all.x=TRUE)
Animals$Species[is.na(Animals$Species)] <- 0


来源:https://stackoverflow.com/questions/38896518/grouped-barplot-order-x-axis-keep-constant-bar-width-in-case-of-missing-leve

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!