0

The context

The following data set contains information on how many bad, alright and good students there are in the departments of a school.

students <- data_frame(
    department = factor(c("Maths", "Physics", "Economics")),
    bad = c(15, 20, 8),
    alright = c(10, 22, 17),
    good = c(8, 12, 5)
)

I tidy the data set and then use it to make a stacked bar chart to visualize the numbers of students in each category and in each department:

tidy_students <- students %>% 
    gather(key = "student_quality", value = "number", -department)

ggplot(data = tidy_students, aes(x = department, y = number, fill = student_quality)) +
    geom_bar(stat = "identity") +
    coord_flip()

enter image description here

My goal

I would like to be able to reorder the bars according to the sub-categories of students. For example, if I want to reorder the bars in descending order based on the number of alright students, then the bar on top would be for the Physics department, followed by the Economics bar and finally the Maths bar.

The actual data I am working with has many more categories (departments) and sub-categories (student quality) and I would like to be able to reorder the bar according to any sub-category.

How can I achieve this? Your help is much appreciated.

SavedByJESUS
  • 3,262
  • 4
  • 32
  • 47
  • 2
    [This question](https://stackoverflow.com/questions/36986699/ggplot2-create-ordered-group-bar-plot-use-reorder) looks like a possible duplicate. Based on the chosen answer there, you could do something like `x = reorder(department, number*(student_quality == "alright"))` for your x variable in `aes()`. – aosmith Jul 27 '18 at 18:02

1 Answers1

1

The bars are ordered according to the levels of the factor. In your case, these are

levels(tidy_students$department)
## [1] "Economics" "Maths"     "Physics"

and the bars are plotted in that order starting at the bottom. All you have to to to change this is to change the order of the levels in the factor. For example, you could just specify your desired order explicitly:

tidy_students$department <- factor(tidy_students$department,
                                   levels = c("Maths", "Economics", "Physics"))

So, your question basically boils down to producing a vector that contains the levels in your desired order.

I show you how to do this for the example that you propose in your question: order the bars in descending order based on the number of alright students. Since the bars are plotted starting at the bottom, I have to create exactly the opposite ordering of that:

library(dplyr)
ordered <- filter(tidy_students, student_quality == "alright") %>%
            arrange(number)
tidy_students$department <- factor(tidy_students$department, levels = ordered$department)

ggplot(data = tidy_students, aes(x = department, y = number, fill = student_quality)) +
    geom_bar(stat = "identity") +
    coord_flip()

enter image description here

You could also sort in descending order using arrange(desc(number)) instead.

Stibu
  • 15,166
  • 6
  • 57
  • 71