I make a bar plot with two factors, one lays on the x axis and the other determines the fill color of the bars. I want to be the bars ascending from left to right within each x factor level. Further, I want the x levels to be ordered ascending, too, based on the smallest y group of each x factor level. I found a similiar question and tried this:
library(ggplot2)
library(tidyverse)
# Finding the right x levels order.
manufacturer_order <- mpg %>%
dplyr::group_by(manufacturer, class) %>%
dplyr::summarise(num= dplyr::n()) %>%
dplyr::group_by(manufacturer) %>%
dplyr::arrange(num, .by_group = TRUE) %>%
dplyr::mutate(dupl= duplicated(manufacturer)) %>%
dplyr::filter(!dupl) %>%
dplyr::arrange(num) %>%
.$manufacturer
# Finding the right y order in each x level.
mpg_ordered <- mpg %>%
dplyr::mutate(manufacturer= factor(manufacturer, levels= manufacturer_order)) %>%
dplyr::arrange(manufacturer) %>%
dplyr::group_by(manufacturer, class) %>%
dplyr::summarise(num= dplyr::n()) %>%
dplyr::group_by(manufacturer) %>%
dplyr::arrange(num, .by_group = TRUE)
# Plot.
mpg_ordered %>%
ggplot(., aes(x= manufacturer, y= num, fill= class)) +
geom_bar(stat= "identity", position = "dodge", color='black')
This is not what I want. The manufacturer
levels are sorted as expected but not the class
levels within each manufacturer
level. For example, within first manufacturer
level nissan the order should be compact, suv and midsize. Of course I can change the order of the fill color variable class
, but the problem is that the order is not the same in all the manufacturer
factor levels. Basically, all bars should have the same order as the rows in my data mpg_ordered
:
> mpg_ordered
# A tibble: 32 x 3
# Groups: manufacturer [15]
manufacturer class num
<fct> <chr> <int>
1 nissan compact 2
2 nissan suv 4
3 nissan midsize 7
4 audi midsize 3
5 audi compact 15
6 lincoln suv 3
7 land rover suv 4
8 mercury suv 4
9 subaru compact 4
10 subaru subcompact 4
# i 22 more rows
# i Use `print(n = ...)` to see more rows
Thus the plot I expect has an ordering similiar to the question linked above (this question):
(but the answer provided there seems not to work)
One option to achieve your desired result would be to create a helper column as the interaction
of the x
and fill
variable which could then be mapped on the group
aes:
library(tidyverse)
mpg |>
count(manufacturer, class, name = "num") |>
mutate(manufacturer = reorder(manufacturer, num, FUN = min)) |>
# Create a helper column to set the order
arrange(manufacturer, num) |>
mutate(
class_ordered = interaction(manufacturer, class),
class_ordered = fct_inorder(class_ordered)
) |>
ggplot(aes(
x = manufacturer, y = num, fill = class,
group = class_ordered
)) +
geom_col(position = "dodge", color = "black")