2

I am attempting to produce a back-to-back bar plot (aka population pyramid plot) using ggplot2. Here is an example:

copied from PopulationPyramid.net

There are multiple examples of creating these plots on S/O (e.g., here, here and here), but none of the solutions offered in these examples are working for me. I wonder whether this is due to these questions being asked a while ago with multiple ggplot updates in-between.

Here is an example of the data I am working with:

dt = structure(list(age_grp = structure(c(1L, 1L, 2L, 2L, 3L, 3L, 
4L, 4L, 5L, 5L, 6L, 6L, 7L, 7L, 8L, 8L, 9L, 9L, 10L, 10L), .Label = c("13", 
"14", "15", "16", "17", "18", "19", "20", "21", "22"), class = "factor"), 
    sex = structure(c(2L, 1L, 2L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 
    2L, 1L, 2L, 1L, 2L, 1L, 1L, 2L, 1L, 2L), .Label = c("Female", 
    "Male"), class = "factor"), percent = c(0.0407730571638261, 
    0.0536480686695279, 0.0652368914621218, 0.0268240343347639, 
    1.22319171491478, 1.07296137339056, 4.02360515021459, 4.89276685965914, 
    16.4967811158798, 19.5710674386366, 24.4638342982957, 20.118025751073, 
    17.9401451520835, 17.1673819742489, 13.0473782924244, 14.7532188841202, 
    13.412017167382, 10.6009948625948, 12.8755364806867, 8.15461143276523
    )), row.names = c(NA, -20L), class = c("data.table", "data.frame"
))

My first attempt at making a pyramid plot used this code:

ggplot(dt, aes(x = age_grp, y = percent, fill = sex)) +
  geom_bar(data = subset(dt, sex == "Female"), stat = "identity") +
  geom_bar(data = subset(dt, sex == "Male"), stat = "identity") +
  coord_flip()

And produced this plot:

Bad plot

You can see that the fill for male has just overlapped the fill for female, rather than the female fill being flipped.

To fix this, I used the following work-around:

ggplot(dt, aes(x = age_grp, y = percent, fill = sex)) +
  geom_bar(data = subset(dt, sex == "Female"), aes(y = -percent), stat = "identity") +
  geom_bar(data = subset(dt, sex == "Male"), stat = "identity") +
  coord_flip()

And this produced a plot close to what I was after:

enter image description here

However, the problem now is that the "percent" y-axis is now negative for females. How do I make it so that the y-axis is positive for both males and females? I'm sure this is an easy fix and I am missing something very simple!

Any help is greatly appreciated

jmogil
  • 143
  • 8

1 Answers1

1

I missed a solution in this post!

Here is the solution:

ggplot(dt, aes(x = age_grp, y = percent, fill = sex)) +
  geom_bar(data = subset(dt, sex == "Female"), aes(y = -percent), stat = "identity") +
  geom_bar(data = subset(dt, sex == "Male"), stat = "identity") +
  scale_y_continuous(breaks=seq(-20,20,5),labels=abs(seq(-20,20,5))) + 
  coord_flip()

Just needed to re-format the labels of the y-axis using scale_y_continuous

jmogil
  • 143
  • 8