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
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()