Search code examples
rggplot2facetr-factor

Exclude unused factor levels in each facet in ggplot


consider this data frame:

df <- data.frame(vars=c(rnorm(3),rnorm(3,2,1), rnorm(3,1,1)),
             names=c("a","b","c","a","d","b","c","a","f"),
             groups=c(rep("x",3),rep("y",3),rep("z",3)))

I'm plotting this with ggplot:

ggplot(df, aes(reorder(names, vars), names)) +    geom_bar(stat="identity") +
theme_bw() + facet_grid(groups~., scales="free_x") + coord_flip() +     ylab(NULL) + xlab(NULL)

it looks like this

enter image description here

I now want the following:

  • each grid item should drop the unused items, e.g. in the "x" grid there should be no "d" and "f"
  • the x axis should be the the value of the "vars" column. The proportions in each grid should be the same, the overall x scale should be dropped. I just want the proportions of the bars in each grid intact
  • the bars should be in decreasing order in each grid (longer bars on top)

update:

Edit using the advice from here I get this error:

ggplot(df, aes(names,vars)) + geom_bar(stat="identity") + coord_flip() + 
  theme_bw() + facet_wrap(~groups,nrow = 3,scales = "free_x")

Error in facet_render.wrap(plot$facet, panel, plot$coordinates, theme,  : 
  ggplot2 does not currently support free scales with a non-cartesian    coord or coord_flip.
In addition: Warning message:
Stacking not well defined when ymin != 0 

when I remove coord_flip() it works but I still get the warning and the result is not what I want.


Solution

  • This is a bit of a workaround but it gives a plot a plot which seems to meet your basic objectives. geom_bar is replaced with geom_seqment because that seems closer to what you're plotting and avoids the complications of coord_flip. The order of the bars is determined by the rank of vars in each group. The y axis labels can't be specified directly but you can use geom_text to place the proper names values next to the y axis so these act as labels. Also, I switched the facet label to the left side which seemed to improve the overall appearance of the facet and y axis labels.

    set.seed(177)
    df <- data.frame(vars=c(rnorm(3),rnorm(3,2,1), rnorm(3,1,1)),
                     names=c("a","b","c","a","d","b","c","a","f"),
                     groups=c(rep("x",3),rep("y",3),rep("z",3)))
    
    library(ggplot2)
    sp1 <- ggplot(data=transform(df, ranked=ave(vars, groups, FUN=rank)),
                      aes( x=vars, y=ranked))
    sp1 <- sp1 + geom_segment( aes( xend = 0,  yend = ranked), size=10)
    sp1 <- sp1 + geom_text( aes( x = min(vars), y= ranked, label = names), hjust= 4)
    sp1 <- sp1 + scale_y_discrete(label=NULL)
    sp1 <- sp1 + theme_bw()
    sp1 <- sp1  + facet_grid( groups ~ .,  scales="free", switch="y")
    plot(sp1)
    

    Plot looks like

    enter image description here