Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reordering geom_bar when using facet_wrap

Tags:

r

ggplot2

What I try to achieve is having the bars ordered by a given variable per panel.

A simple example:

    library(ggplot2)
    library(plyr)

    df <- data.frame(fac = c("a", "b", "c", "e", "b", "c", "d"),             
                  val = c(1, 2, 7, 4, 5, 3, 1),
                  group = c(1, 1, 1, 1, 2, 2, 2))

    p1 <- ggplot(df, aes(x = fac, y = val)) + geom_bar() + facet_wrap(~ group, scales = "free") + coord_flip()
    p1

    p2 <- ggplot(df, aes(x = reorder(fac, val), y = val)) + geom_bar() + facet_wrap(~ group, scales = "free") + coord_flip()
    p2

p2 does not produce what I want because not every "factor level" appears in all panels. Is there a simple solution already for this problem?

One solution I found is the following (calculates the rank for each factor level per group).

df2 <- ddply(df, .(group), transform, fac2 = rank(val))
df2$fac2 <- factor(df2$fac2)
p3 <- ggplot(df2, aes(x = fac2, y = val)) + facet_wrap(~ group, scales = "free") + geom_bar(stat = "identity") + coord_flip() +
  opts(panel.margin = unit(2, "lines"))
p3

I have to set the labels by my self here. One possible solution is the following (hard coded for this example):

grid.newpage()
grob <- ggplotGrob(p3)
object.path <- grid.ls(getGrob(grob, "axis.text.y", grep = TRUE, global = TRUE), print = FALSE)$name
grob <- grid::editGrob(grob, object.path[1], label = c("ABDQ", "M", "A", "B"))
grob <- grid::editGrob(grob, object.path[2], label = c("A", "B", "EEEEX"))
grid.draw(grob)

But there is another problem. I have to set the panel.margin by my self now and it seems to be not possible to do this as I'm only able to set a "global" panel.margin and what I need is one for all 4 sides (or at least 2).

Question 1: Is there a simple solution using reorder?

Question 2: Is there a solution using scale_x_discrete to get the needed axis?

Question 3: I wasn't able to find the needed grid object to manipulate the viewports for the panel.margins. Is there an easy way to manipulate the appropriate grid object?

Any ideas?

like image 548
user1901670 Avatar asked Dec 13 '12 17:12

user1901670


People also ask

How do I reorder facets in R?

To reorder the facets accordingly of the given ggplot2 plot, the user needs to reorder the levels of our grouping variable accordingly with the help of the levels function and required parameter passed into it, further it will lead to the reordering of the facets accordingly in the R programming language.

What is the difference between Facet_wrap and Facet_grid?

While facet_grid shows the labels at the margins of the facet plot, facet_wrap creates a label for each plot panel.

How do you arrange a bar graph in descending order in R?

Rearranging Results in Basic R Then draw the bar graph of the new object. If you want the bar graph to go in descending order, put a negative sign on the target vector and rename the object. Then draw the bar graph of the new object.

What does Facet_wrap do in Ggplot?

facet_wrap() makes a long ribbon of panels (generated by any number of variables) and wraps it into 2d. This is useful if you have a single variable with many levels and want to arrange the plots in a more space efficient manner.


1 Answers

I think that grid.arrange is a much better tool for this than trying to shoehorn free scales into a faceting framework:

library(gridExtra)
q1 <- ggplot(subset(df,group == 1),aes(x = reorder(fac,val),y = val)) + 
        geom_bar() + 
        facet_wrap(~group) + 
        coord_flip()

q2 <- q1 %+% subset(df,group == 2)

grid.arrange(q1,q2,nrow = 1)

enter image description here

like image 199
joran Avatar answered Sep 29 '22 03:09

joran