heds1
heds1

Reputation: 3438

Reorder columns by value while maintaining group order

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.

first_image

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")

image2

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.

image3

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

Answers (2)

lroha
lroha

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() 

enter image description here

Upvotes: 5

ThomasPepperz
ThomasPepperz

Reputation: 176

Use function fct_infreq( )


ggplot(df2, aes(fct_infreq(x),y))+
 geom_col()

Upvotes: 0

Related Questions