2

I am trying to disable the alphabetical reordering of the x variable in a geom_bar. I see lots of questions and answers around how to reorder the x variable in a simple bar chart (e.g. here, here, here), but each of the answers introduces complexity which is not necessary if the order can be left in tact

Is there any way to pipe a pre-arranged data.frame to a geom_bar() and have the alphabetical reordering deactivated so that the resulting bar chart simply displays x in the order that x appears in the data.frame?

Example

Suppose we have some data that is already ordered the way it should be plotted


df <- structure(list(software = c("Python", "R", "SQL", "Hadoop", "Tableau", 
                                  "Scala", "SAS", "Java", "C", "Spark"), users = c(6440, 5750, 4725,1755, 1660, 1560, 1490, 965, 875, 830)), row.names = c(NA, -10L), class = "data.frame")


#   software users
# 1    Python  6440
# 2         R  5750
# 3       SQL  4725
# 4    Hadoop  1755
# 5   Tableau  1660
# 6     Scala  1560
# 7       SAS  1490
# 8      Java   965
# 9         C   875
# 10    Spark   830



df %>% ggplot(aes(software, users)) + geom_bar(stat = "identity") +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

This reorders x - how can we force the geom_bar to not reorder the columns alphabetically so that the resulting bar chart displays x in the order in which it appears in the data.frame, and so that we do not have to do any further reordering?

stevec
  • 41,291
  • 27
  • 223
  • 311

2 Answers2

4

Change it to factor and arrange them based on the occurrence.

library(dplyr)
library(ggplot2)

df %>% 
  mutate(software = factor(software, levels = unique(software))) %>%
  ggplot() + aes(software, users) + geom_bar(stat = "identity") +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

enter image description here

To rearrange without changing the column to factors, we can use reorder

ggplot(df) + aes(reorder(software, match(software,unique(software))), users) + 
geom_bar(stat = "identity") +
theme(axis.text.x = element_text(angle = 90, hjust = 1))
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • Is there any way of doing this without changing the input data.frame? (e.g. without changing to a factor?) – stevec Mar 14 '20 at 05:32
4

Alternatively, jou can also simply set the limits of the x axis, which saves you from fumbling with factors:

df %>% ggplot(aes(software, users)) + 
    geom_col() + 
    scale_x_discrete(limits = unique(df$software))
    theme(axis.text.x = element_text(angle = 90, hjust = 1))

Friendly reminder: geom_col() is the same as geom_bar(stat = "identity"), but shorter.

teunbrand
  • 33,645
  • 4
  • 37
  • 63