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()
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.
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()
You could also sort in descending order using arrange(desc(number))
instead.