Reputation: 3438
My data (reproduced below) contain three variables, Tools
(categorical variable), Proficiency
(value column) and Category
(grouping column).
I would like to sort the columns based on descending order of Proficiency
value, while maintaining separation of Category
groups, and without using facet_grid
or facet_wrap
(because I am using coord_flip
). Reproducible data is below. To sort by Category
, I specify the levels of Tools
based on the Category
factor.
library(tidyverse)
df1 <- structure(list(Tools = structure(c(1L, 8L, 9L, 5L, 6L, 10L, 2L,
3L, 4L, 7L), .Label = c("Tool1", "Tool7", "Tool8", "Tool9", "Tool4",
"Tool5", "Tool10", "Tool2", "Tool3", "Tool6"), class = "factor"),
Proficiency = c(3, 2, 5, 4, 3, 3, 3, 2, 2, 2), Category = structure(c(1L,
3L, 3L, 2L, 2L, 3L, 1L, 1L, 1L, 2L), .Label = c("Category1",
"Category2", "Category3"), class = "factor")), row.names = c(NA,
-10L), class = "data.frame")
df1$Tools <- factor(df1$Tools, levels = df1$Tools[order(df1$Category)])
ggplot(data = df1, aes(x = Tools, y = Proficiency, fill = Category)) +
geom_col() +
scale_x_discrete(limits = rev(levels(df1$Tools)))
This produces the below plot, which is obviously not grouped in descending order of Proficiency
value.
One way to accomplish the desired grouping and sorting is by using facet_grid()
and reordering Tools
based on Proficiency
within the aes
call:
ggplot(data = df1, aes(x = reorder(Tools, -Proficiency), y = Proficiency, fill = Category)) +
geom_col() +
facet_grid(~ Category, scales = "free_x", space = "free_x")
However, I would like to use coord_flip
for this plot. Unfortunately, coord_flip
does not seem to work well with facet_grid
(github issues one, two)
.
Predictably, sorting by Proficiency
without using facet_grid
causes the plot to override the Category
groups.
My desired output is the above image, where the Tools
are sorted firstly by Category
, and secondarily by Proficiency
. Any help is much appreciated.
This answer looked promising, but applying a similar approach here didn't work for me; the below manipulation just set up the plot for ordering via Proficiency
:
df1$Tools <- with(df1, factor(Tools, levels=Tools[order(ave(Proficiency, Category, FUN=min),Proficiency)]))`
Upvotes: 3
Views: 1775
Reputation: 34301
One way is to arrange your dataframe into the desired order and set the factor levels of Tools
with that order.
library(dplyr)
library(ggplot2)
df1 %>%
arrange(desc(Category), desc(Proficiency)) %>%
mutate(Tools = factor(Tools, levels = Tools)) %>%
ggplot(aes(x = Tools, y = Proficiency, fill = Category)) +
geom_col() +
coord_flip()
Upvotes: 5
Reputation: 176
Use function fct_infreq( )
ggplot(df2, aes(fct_infreq(x),y))+
geom_col()
Upvotes: 0