I’m trying to overlay two population pyramid plots in one ggplot2 plot. I first created a plot using the census data with lighter colors and then try to superimpose another plot (created using the survey data with darker colors, say darkred, steelblue) onto the former. Is there any way I can do that while having their gender (sex) labels displayed on the legend? (Male (c/s) refers to Male (census/survey), the same goes to Female). This post is a reference.
library(tidyverse)
library(ggplot2)
# create data
census <- data.frame(age = c("20-29", "30-39", "40-49", "50-59", "60-69", "70+"), PopPerc = c(12.45, 14.14, 16.56, 14.73, 13.77, 11.00, -11.18, -13.13, -16.67, -15.10, -14.60, -13.82), sex = c("Male (c)", "Male (c)", "Male (c)", "Male (c)", "Male (c)", "Male (c)", "Female (c)", "Female (c)", "Female (c)", "Female (c)", "Female (c)", "Female (c)"), signal = c(1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1))
survey <- data.frame(age = c("20-29", "30-39", "40-49", "50-59", "60-69", "70+"), PopPerc = c(12.18, 24.70, 27.54, 19.22, 11.77, 4.60, -11.94, -25.76, -29.59, -18.11, -10.84, -3.76), sex = c("Male (s)", "Male (s)", "Male (s)", "Male (s)", "Male (s)", "Male (s)", "Female (s)", "Female (s)", "Female (s)", "Female (s)", "Female (s)", "Female (s)"), signal = c(1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1))
# create base plot using census data
base <- census %>%
ggplot() + # build the plot with ggplot2
geom_bar(aes(x = age, y = PopPerc, fill = sex), stat = 'identity') +
geom_text(aes(
# create the text
x = age,
y = PopPerc + signal * .3,
label = abs(PopPerc)
)) +
coord_flip() + # flip the plot
scale_fill_manual(name = '', values = alpha(c('lightpink', 'lightblue1'), alpha = 0.5)) + (darkred = female, steelblue = male)
scale_y_continuous(
# scale the y-lab
labels = function(x) {
paste(abs(x), '%')
}
) +
labs(
# name the labs
x = '',
y = 'Participants by %',
title = ''
) +
theme(
# costume the theme
axis.text.x = element_text(vjust = .5),
panel.grid.major.y = element_line(color = 'lightgray', linetype =
'dashed'),
legend.position = 'top',
legend.justification = 'center'
) +
theme_classic()
base
>Solution :
I’m not a 100% clear on what you want, but I think this should get you started at least. I bind the two data.frames together, like so:
bind_rows(census, survey, .id = 'type') %>%
ggplot() +
geom_col(aes(PopPerc, age, fill = sex), position = 'identity', alpha = 0.5) +
geom_text(aes(PopPerc + signal * 1, age, label = abs(PopPerc))) +
scale_fill_manual(values = c('lightpink', 'darkred', 'lightblue1', 'steelblue')) +
scale_x_continuous(labels = \(x) paste(abs(x), '%')) +
labs(
# name the labs
x = 'Participants by %',
y = NULL, fill = NULL
) +
theme(
# customize the theme
axis.text.x = element_text(vjust = .5),
panel.grid.major.y = element_line(color = 'lightgray', linetype = 'dashed'),
legend.position = 'top',
legend.justification = 'center'
) +
theme_classic()
