'How to make expand_limits dynamic in a pyramid chart?
I want to make a population pyramid chart to display differences of age and gender among different jobs in the DF i have (small sample below). I want to make the all the graphs automatically without having to change the code manually as it would be do time consuming for all jobs in my original DF. Making a pyramid chart in ggplot is hard but possible but i do not know how to automate it fully. I have two problems
Currently i need to set expand limits manually. As in some jobs there are more men and in some more women. Even if i leave the length of the y-axis the same for all jobs (big and small), then i need to change the -/+ in expand_limits manually. Can i automate it somehow or give both expand limits -15000 and 15000 at the same time? Fright now i'm only manipulating one axis. (expand_limits(y=-15000).
A Bonus but problem, that would be great if we could solve it but it's not a must. Is it possible to make y axis length and expand_limits dynamic so that it fits big and small jobs. For example:
Builders
expand_limits(y=-15000)+
scale_y_continuous(breaks =c(-15000,-7500,0,7500,15000),
label =c(15000,7500,0,7500,15000))+
Civil servants
expand_limits(y=-500)+
scale_y_continuous(breaks =c(-500,-250,0,250,500),
label =c(500,250,0,250,500))+
Any help is highly appreciated
Example DF
Job Age Gender People Builder 25-34 M 12752 Builder 25-34 F 386 Builder 35-44 M 13980 Builder 35-44 F 390 Builder 45-54 M 9686 Builder 45-54 F 361 Builder 55-64 M 4924 Builder 55-64 F 334 Builder 65+ M 961 Builder 65+ F 69 Builder Under 25 M 4639 Builder Under 25 F 200 Civil servant 25-34 M 88 Civil servant 25-34 F 274 Civil servant 35-44 M 58 Civil servant 35-44 F 464 Civil servant 45-54 M 45 Civil servant 45-54 F 523 Civil servant 55-64 M 43 Civil servant 55-64 F 234 Civil servant 65+ M 12 Civil servant 65+ F 121 Civil servant Under 25 M 21 Civil servant Under 25 F 76
My code
Pyramid <-Pyramid %>%
filter(Job == "Builder") #"Civil servant" for other job in the example.
Pyramid$People <- ifelse(Pyramid$Gender == "M",Pyramid$People*-1, Pyramid$People)
Pyramid$Age <- fct_relevel(Pyramid$Age, "Under 25","25-34","35-44","45-54","55-64","65+")
ggplot(Pyramid ,aes(x=Age, y=People, fill=Gender))+
geom_bar(data = subset(Pyramid, Gender =="F"), stat = "identity")+
geom_bar(data = subset(Pyramid, Gender =="M"), stat = "identity")+
coord_flip()+
theme_minimal(base_size = 17)+
scale_fill_manual(values = c("M" = "#0071ce",
"F" = "#d30031"),
name=" ",
labels=c("Men","Women"))+
expand_limits(y=-15000)+ #This is the problem line for me
scale_y_continuous(breaks =c(-15000,-7500,0,7500,15000), #And these two lines as well
label =c(15000,7500,0,7500,15000))+
ylab(NULL)+
theme(legend.position = "bottom",
axis.title.y=element_blank())
This is what i would like, for different jobs the expand limits needs to be different +/-

This is with expand_limits removed

Expand_limits centers the genders
Solution 1:[1]
Try this:
library(tidyverse)
Pyramid <- tribble(
~Job, ~Age, ~Gender, ~People,
"Builder", "25-34", "M", 12752,
"Builder", "25-34", "F", 386,
"Builder", "35-44", "M", 13980,
"Builder", "35-44", "F", 390,
"Builder", "45-54", "M", 9686,
"Builder", "45-54", "F", 361,
"Builder", "55-64", "M", 4924,
"Builder", "55-64", "F", 334,
"Builder", "65+", "M", 961,
"Builder", "65+ ", "F", 69,
"Builder", "Under 25", "M", 4639,
"Builder", "Under 25", "F", 200,
"Civil servant", "25-34", "M", 88,
"Civil servant", "25-34", "F", 274,
"Civil servant", "35-44", "M", 58,
"Civil servant", "35-44", "F", 464,
"Civil servant", "45-54", "M", 45,
"Civil servant", "45-54", "F", 523,
"Civil servant", "55-64", "M", 43,
"Civil servant", "55-64", "F", 234,
"Civil servant", "65+", "M", 12,
"Civil servant", "65+", "F", 121,
"Civil servant", "Under 25", "M", 21,
"Civil servant", "Under 25", "F", 76
)
data_df <- Pyramid %>%
filter(Job == "Builder") %>%
mutate(
People = if_else(Gender == "M", People * -1, People),
Age = factor(Age, levels = c("Under 25", "25-34", "35-44", "45-54", "55-64", "65+"))
)
max <- max(abs(data_df$People))
min <- max * -1
data_df %>%
ggplot(aes(Age, People, fill = Gender)) +
geom_col() +
coord_flip() +
theme_minimal(base_size = 17) +
scale_fill_manual(values = c("#d30031", "#0071ce")) +
scale_y_continuous(limits = c(min, max)) +
labs(y = NULL, fill = NULL) +
theme(legend.position = "bottom")

Created on 2022-05-07 by the reprex package (v2.0.1)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Carl |
