2

This is different to existing questions. Other answers pointed to refer to moving entire bars according to a specified order. I would like to sort the resulting bars according to one element within the stacked bars.

I've created a stacked bar plot in R. This is the data set:

dput(Pitch_third)
structure(list(Team = c("Millwall", "Birmingham", "Sheffield United",
                        "Rotherham", "Middlesbrough", "Wigan", "Aston Villa", "Blackburn",
                        "Bolton", "Brentford", "Bristol City", "Leeds", "Preston", "Queens Park Rangers",
                        "Stoke", "Derby", "Ipswich", "Norwich", "West Bromwich Albion",
                        "Nottingham Forest", "Swansea", "Hull", "Reading", "Sheffield Wednesday"), 
               Own_3rd = c(0.25, 0.25, 0.25, 0.29, 0.27, 0.28, 0.28, 0.3, 
                           0.29, 0.28, 0.28, 0.3, 0.28, 0.3, 0.27, 0.28, 0.3, 0.29, 0.29, 
                           0.3, 0.31, 0.3, 0.3, 0.31), 
               Middle_3rd = c(0.41, 0.42, 0.43, 
                              0.4, 0.43, 0.42, 0.44, 0.41, 0.42, 0.42, 0.43, 0.42, 0.42, 0.42, 
                              0.45, 0.45, 0.43, 0.44, 0.44, 0.43, 0.44, 0.45, 0.45, 0.45), 
               Final_3rd = c(0.35, 0.33, 0.32, 0.31, 0.3, 0.3, 0.29, 0.29, 
                             0.29, 0.29, 0.29, 0.29, 0.29, 0.29, 0.28, 0.27, 0.27, 0.27, 
                             0.27, 0.26, 0.26, 0.25, 0.25, 0.25)), 
          row.names = c(NA, -24L), 
          class = "data.frame")

Then I've created a tibble called Pitch_third from this data. Then plotted it with this:

Pitch_third %>%
gather(variable, value, Own_3rd:Final_3rd) %>% 
ggplot(aes(x = Team, y = value, fill = variable)) + 
geom_bar(position = "fill", stat = "identity") +
coord_flip()

This is the resulting plot:

How can I sort the plot so that teams are sorted by the variable Final_3rd rather than alphabetically?

I have tried to use arrange() to sort the tibble by Final_3rd but I think gather() might be messing with that after.

Pitch_third <- arrange(Pitch_third, desc(Final_3rd))
Valentin_Ștefan
  • 6,130
  • 2
  • 45
  • 68
Mr_Percy_Heat
  • 59
  • 1
  • 10

2 Answers2

0

I assume you want this: this

Using your data as data

library(data.table)
library(tidyr)

data2 <- as.data.table(gather(data, variable, value, Own_3rd:Final_3rd))

team_levels <- unique(data2[, Team])[order(data2[variable == "Final_3rd", value])]

data2$Team2 <- factor(data2$Team, levels = team_levels)

ggplot(data = data2,
       aes(x = Team2, y = value, fill = variable)) +
  geom_bar(position = "fill", stat = "identity") +
  coord_flip()

Answer based on: Change the order of a discrete x scale

Fernando
  • 126
  • 9
  • Thanks very much for that. I shall study it to try and learn as much as possible from your answer. One thing that puzzles me is why some teams appear out of order. Nottingham Forest and Preston, for eg, appear to have slipped down by a place, with also a bit of a bulge in the middle of the ranking. Any idea why that happens? – Mr_Percy_Heat Jan 17 '19 at 21:55
  • Edited to add: It's caused by variation in the percentages. They don't all add up to 100. – Mr_Percy_Heat Jan 17 '19 at 22:05
  • Just noticed that. There are two things that you need to learn from my answer: `data.table` and `tidyr`. Those united with `ggplot` are in my opinion the perfect combination for exploratory analysis and graphics – Fernando Jan 17 '19 at 22:09
0

I think you did a great job already and you got it right with the arrange, which should be placed after gather. Then a trick could be to get a new factor for Team with the levels sorted according to "Final_3rd"'s values, rather than the default alphabetical order.

library(ggplot2)
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(tidyr)

Pitch_third %>%
  gather(variable, value, Own_3rd:Final_3rd) %>% 
  arrange(variable, value) %>% 
  # Create a new factor, with its levels sorted according to Final_3rd
  mutate(team_f = factor(Team, levels = .[.$variable == "Final_3rd", "Team"])) %>% 
  # or
  # mutate(team_f = factor(Team, levels = filter(., variable == "Final_3rd") %>% .$Team)) %>%
  ggplot(aes(x = team_f, y = value, fill = variable)) +
  geom_bar(position = "fill", stat = "identity") +
  coord_flip()

Created on 2019-01-17 by the reprex package (v0.2.1)

Valentin_Ștefan
  • 6,130
  • 2
  • 45
  • 68