Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to order bars in faceted ggplot2 bar chart

If I want to order the bars in a ggplot2 barchart from largest to smallest, then I'd usually update the factor levels of the bar category, like so

one_group <- data.frame(
  height   = runif(5),
  category = gl(5, 1)
)

o <- order(one_group$height, decreasing = TRUE)
one_group$category <- factor(one_group$category, levels = one_group$category[o])

p_one_group <- ggplot(one_group, aes(category, height)) +
  geom_bar(stat = "identity")
p_one_group

If have have several groups of barcharts that I'd like in different facets, with each facet having bars ordered from largest to smallest (and different x-axes) then the technique breaks down.

Given some sample data

two_groups <- data.frame(
  height   = runif(10),
  category = gl(5, 2),
  group    = gl(2, 1, 10, labels = letters[1:2])
)

and the plotting code

p_two_groups <- ggplot(two_groups, aes(category, height)) +
  geom_bar(stat = "identity") +
  facet_grid(. ~ group, scales = "free_x")
p_two_groups

what do I need to do to get the bar ordering right?

If it helps, an equivalent problem to solve is: how do I update factor levels after I've done the faceting?

like image 874
Richie Cotton Avatar asked Mar 23 '11 18:03

Richie Cotton


People also ask

How do I rearrange bars in ggplot2?

Reordering in ggplot is done using theme() function. Within this, we use axis. text. x with the appropriate value to re-order accordingly.

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 facet wrap in ggplot2?

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. You can control how the ribbon is wrapped into a grid with ncol , nrow , as.


2 Answers

here is a hack:

two_groups <- transform(two_groups, category2 = factor(paste(group, category)))
two_groups <- transform(two_groups, category2 = reorder(category2, rank(height)))

ggplot(two_groups, aes(category2, height)) +
  geom_bar(stat = "identity") +
  facet_grid(. ~ group, scales = "free_x") +
  scale_x_discrete(labels=two_groups$category, breaks=two_groups$category2)
  1. make UNIQUE factor variable for all entries (category2)
  2. reorder the variable based on the height
  3. plot on the variable: aes(x=category2)
  4. re-label the axis using original value (category) for the variable (category2) in scale_x_discrete.
like image 185
kohske Avatar answered Sep 23 '22 17:09

kohske


Here is a hack to achieve what you want. I was unable to figure out how to get the category values below the tick marks. So if someone can help fix that, it would be wonderful. Let me know if this works

# add a height rank variable to the data frame
two_groups = ddply(two_groups, .(group), transform, hrank = rank(height));

# plot the graph

p_two_groups <- ggplot(two_groups, aes(-hrank, height)) +
  geom_bar(stat = "identity") +
  facet_grid(. ~ group, scales = "free_x") +
  opts(axis.text.x = theme_blank()) +
  geom_text(aes(y = 0, label = category, vjust = 1.5))
like image 38
Ramnath Avatar answered Sep 21 '22 17:09

Ramnath