Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flip order of data in grouped bar plot after coord_flip

Tags:

r

ggplot2

I've been having an annoying issue for which I haven't been able to find a specific solution. I'm trying to create a horizontal grouped bar plot; All I want is to take the standard vertical bar plot and rotate it 90 degrees to the right. When I use coord_flip, it rotates the plot to the right, but flips (reverses) the order of the data within each group. Here's an example:

library("ggplot2")

df <- data.frame(Group = c("A","A","A","B","B","B","C","C","C"),
                 Sub = c("1","2","3","1","2","3","1","2","3"),
                 Score = c(1,2,3,1,2,3,1,2,3))

df$Group <- factor(df$Group,
                       levels = c("A","B","C"),
                       labels = c("A","B","C"),
                       ordered = TRUE)

df$Sub <- factor(df$Sub,
                  levels = c("1","2","3"),
                  labels = c("1","2","3"),
                  ordered = TRUE)

ggplot(data = df, aes(x = Group, y = Score, fill = Sub)) +
  geom_bar(stat="identity", position=position_dodge()) +
  coord_flip() +
  scale_x_discrete(limits = rev(levels(df$Group)))

I'm able to get the groups in the right order using:

scale_x_discrete(limits = rev(levels(df$Group)))

However, I can't get the order within each group correct. The legend and the data are opposite one another, and in this case, I want to change the order of the plotted data, and not the order of the legend.

I've seen that you can fix the issue by setting the bar plot's position dodge to -.9, like this:

geom_bar(stat="identity", position=position_dodge(-.9))

Given that my grouping variables are strings, I'm not sure the solution proposed here would work.

Any help would be greatly appreciated!

like image 847
pablom Avatar asked Dec 24 '22 04:12

pablom


1 Answers

If you are familiar with the forcats package, fct_rev() is very handy for reversing factor levels while plotting, and the legend order / colour mappings can be reversed back easily to match the original version before flipping your coordinates:

library(forcats)
library(ggplot2)

# unflipped version
p1 <- ggplot(data = df, 
       aes(x = Group, y = Score, fill = Sub)) +
  geom_col(position="dodge") #geom_col is equivalent to geom_bar(stat = "identity")

# flipped version
p2 <- ggplot(data = df, 
       aes(x = fct_rev(Group), y = Score, fill = fct_rev(Sub))) +
  geom_col(position="dodge") +
  coord_flip() +
  scale_fill_viridis_d(breaks = rev, direction = -1)

gridExtra::grid.arrange(p1, p2, nrow = 1)

plot comparison

like image 189
Z.Lin Avatar answered Feb 01 '23 07:02

Z.Lin