ggplot2 bar plot: order fill as in data

时间:2017-05-16 09:38:45

标签: r ggplot2

Giving data frame like this:

sam<-data.table(title=c(rep("Cat",8),rep("Dog",4)),
               fcat=c("A","B","C","B","B","C","C","B","C","B","B","C"),
               fnum=c(seq(8,1),seq(4,1)),
               labeltext=c("Pancakes","Muffins","Baursaq","Muffins","Muffins",
                 rep("Baursaq",3),"Muffins","Baursaq","Baursaq","Muffins"), 
               size=c(10,rep(1,11)))

sam
    title fcat fnum labeltext size
 1:   Cat    A    8  Pancakes   10
 2:   Cat    B    7   Muffins    1
 3:   Cat    C    6   Baursaq    1
 4:   Cat    B    5   Muffins    1
 5:   Cat    B    4   Muffins    1
 6:   Cat    C    3   Baursaq    1
 7:   Cat    C    2   Baursaq    1
 8:   Cat    B    1   Baursaq    1
 9:   Dog    C    4   Muffins    1
10:   Dog    B    3   Baursaq    1
11:   Dog    B    2   Baursaq    1
12:   Dog    C    1   Muffins    1

I want to create a barplot with x=title, y=size, filled by fcat, labelled by labeltext and ordered in descending order by fnum. First approach without reordering the original data. Here I concatenated text of labels in order to check if the order, size and category is used correctly.

ggplot(sam)+
    geom_bar(aes(x=factor(title), y=size,fill=fcat),
             stat="identity", color="white", size=1)+
    geom_text(aes(x=title, y=size,
             label=(paste(labeltext,size,fnum,fcat, sep=" "))),
             size = 3, position = position_stack(vjust = 0.5))+
    ggtitle("Without ordering")

enter image description here

Labels are ordered as needed, but there's a big problem with filling. Reorder filling by fnum:

ggplot(sam)+
    geom_bar(aes(x=factor(title), 
              y=size,fill=reorder(fcat,fnum)),
              stat="identity", color="white", size=1)+
    geom_text(aes(x=title,y=size,
             label=reorder(paste(labeltext,size,fnum,fcat, 
                       sep=" "),fnum)),
             size = 3, position = position_stack(vjust = 0.5))+
    ggtitle("Ordered by fnum")

enter image description here

In this case bars are grouped by wrong fillings. For instance, for "Cat" the graph should plot 1 blue sized 10 bar, then 1 green, 1 red, 2 greens, 2 red, 1 green (as in labeltext's categories). I want the plot to be stripped as in the original data. Like this guy had in first place. stat="identity" doesn't work as expected.

I tried numerous approach reordering, but nothing helps much. I've searched through the SO barplot fill questions in ggplot2 tag (more than 700 posts o_O) and read the documentation very carefully. Nonetheless, no answer was found so far.

2 个答案:

答案 0 :(得分:3)

这是另一种方式

ggplot(sam)+
  geom_bar(aes(x=title, y=size,group=fnum,fill=fcat), #group by fnum and fill with fcat
           stat="identity", color="white", size=1)+
  geom_text(aes(x=title, y=size,
                label=(paste(labeltext,size,fnum,fcat, sep=" "))),
            size = 3, position = position_stack(vjust = 0.5))+
  ggtitle("group by fnum and fill by fcat")

结果:

Github SQLiteAssetHelper example

答案 1 :(得分:1)

我发现了使用geom_tile的黑客攻击:

sam%>%
  group_by(title)%>%
  # set the order you want within each group
  arrange(title, desc(fnum))%>%
  # calculate the (vertical) center of each tile
  mutate(cum_size = cumsum(size) - size / 2)%>%
  ggplot(aes(x=title, y=cum_size, fill = fcat))+
    geom_tile(color="white", size = 1, aes(height = size))+
    geom_text(aes(label=paste(labeltext,size,fnum,fcat,sep=" ")),
              size = 3)

enter image description here