1

Based on the data and code below, how can I sort the bars in descending order for each group?

Purpose: To show count of each FF in descending order for each city by district. This will then show me which city in which district has the highest count of a particular FF. Where FF = Flood factor (risk of flooding) ranging from 1 to 10 so, the plot will show the dominant FF in each city in a district.

Code + data:

df_sample = structure(list(City = c("A", "A", "A", "A", "A", "A", "A", "A", 
"A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", 
"A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", 
"B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", 
"B", "B", "C", "C", "C", "C", "C", "D", "D", "D", "D", "D", "D", 
"D", "D", "D", "D", "D", "D", "D", "D", "D", "E", "E", "E", "E", 
"E", "E", "E", "E", "E", "F", "F", "F", "F", "F", "F", "F", "F", 
"F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F"
), District = c("D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", 
"D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", 
"D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", 
"D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", 
"D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", "D1", 
"D1", "D1", "D2", "D2", "D2", "D2", "D2", "D2", "D2", "D2", "D2", 
"D2", "D2", "D2", "D2", "D2", "D2", "D2", "D2", "D2", "D2", "D2", 
"D2", "D2", "D2", "D2", "D2", "D2", "D2", "D2", "D2", "D2", "D2", 
"D2", "D2", "D2", "D2", "D2", "D2", "D2", "D2", "D2", "D2", "D2", 
"D2", "D2", "D2"), FF = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L)), class = "data.frame", row.names = c(NA, 
-99L))

# Plot
df_sample %>% 
  arrange(desc(FF)) %>% 
  ggplot(aes(x = City,
             y = FF,
             fill = District)) +
  geom_bar(position = "dodge",
           stat = "identity")
Ed_Gravy
  • 1,841
  • 2
  • 11
  • 34
  • 1
    Relevant: https://stackoverflow.com/q/12774210/3358272, https://stackoverflow.com/q/18401931/3358272, and https://stackoverflow.com/q/44350031/3358272 – r2evans Dec 14 '22 at 16:46
  • 1
    By *"count of each `FF`"* do you mean *total* of each `FF` by groups of City and District? – Rui Barradas Dec 14 '22 at 16:49
  • @RuiBarradas, since `FF` is `categorical` so total = `total count`. Like how many times each `FF` appears in each city by district and then arrange that in descending order. – Ed_Gravy Dec 14 '22 at 16:51
  • I have added more context to the question. – Ed_Gravy Dec 14 '22 at 16:56
  • 1
    What is your expected output? – Quinten Dec 14 '22 at 16:58
  • @Quinten honestly I am also thinking what'd be the most suitable plot for such a purpose. So, I am not entirely sure whether a bar plot would be the right way to do it or not. – Ed_Gravy Dec 14 '22 at 17:01

2 Answers2

2

You can reorder City as factor

library(dplyr)
library(ggplot2)
library(forcats)

df_sample %>% 
  mutate(City = fct_rev(fct_reorder2(City,FF,District))) %>%
  # arrange(desc(FF)) %>%
  ggplot(aes(x = City,
             y = FF,
             fill = District)) +
  geom_bar(position = "dodge",
           stat = "identity")

enter image description here

Vinícius Félix
  • 8,448
  • 6
  • 16
  • 32
1

I am not sure that this is what is asked for.

suppressPackageStartupMessages({
  library(dplyr)
  library(ggplot2)
})

df_sample %>%
  group_by(District, City) %>%
  summarise(FF = sum(FF)) %>%
  mutate(City = reorder(City, FF, decreasing = TRUE)) %>%
  ggplot(aes(x = City, FF, fill = District)) +
  geom_col(position = "dodge")
#> `summarise()` has grouped output by 'District'. You can override using the
#> `.groups` argument.

Created on 2022-12-14 with reprex v2.0.2


Edit

Following the OP's comment below, here is a plot of counts.

The counts can be computed as follows.

df_sample %>% count(District, City, FF)
#>   District City FF  n
#> 1       D1    A  1 29
#> 2       D1    B  2 20
#> 3       D1    C  3  5
#> 4       D2    D  1 15
#> 5       D2    E  2  9
#> 6       D2    F  3 21

Created on 2022-12-14 with reprex v2.0.2

And here is the bar plot.

suppressPackageStartupMessages({
  library(dplyr)
  library(ggplot2)
})

df_sample %>%
  group_by(District, City) %>%
  summarise(FF = n()) %>%
  mutate(City = reorder(City, FF, decreasing = TRUE)) %>%
  ggplot(aes(x = City, FF, fill = District)) +
  geom_col(position = "dodge")
#> `summarise()` has grouped output by 'District'. You can override using the
#> `.groups` argument.

Created on 2022-12-14 with reprex v2.0.2


Edit 2

And here is the plot with the counts over the bars and the values of FF in the middle of the bars. This is probably too complicated but it works.

df_sample %>%
  mutate(FF = factor(FF)) %>%
  group_by(District, City, FF) %>%
  summarise(n = n()) %>% 
  group_by(District) %>%
  mutate(
    tmp = as.integer(factor(n)),
    City = reorder(City, tmp, decreasing = TRUE)
  ) %>%
  select(-tmp) %>%
  ggplot(aes(x = City, n, fill = District)) +
  geom_col(position = "dodge") +
  geom_text(aes(label = n), vjust = -1) +
  geom_text(aes(y = n/2, label = FF)) +
  # geom_label(aes(y = n/2, label = FF), fill = "white") +
  ylim(0, 31)
#> `summarise()` has grouped output by 'District', 'City'. You can override using
#> the `.groups` argument.

Created on 2022-12-14 with reprex v2.0.2

Rui Barradas
  • 70,273
  • 8
  • 34
  • 66