The main goal of this visualisation is to visualise the demographic structure of Singapore’s population by age cohort and planning area, in the year 2019. To visualise by age cohort, the classic method would be to use a population pyramid. As for visualising by planning area,
Because there are multiple planning areas, it would be difficult to show it all on one page in a static document. So, we can make use of R functions to create a selection option to view specific visualisations for each planning area as needed.
First, we will load the libraries required, and load the data used for visualisation
packages <- c('tidyverse','shiny','ggthemes')
for(p in packages){
if (!require(p,character.only = T)){
install.packages(p)
}
library(p,character.only = T)
}
data <- read_csv("data/respopagesextod2011to2020.csv")
After which, we can prepare the data for creating a population pyramid.
dataF=filter(data,Sex=="Females")
dataM=filter(data,Sex=="Males")
To be able to create the mirrored symmetrical shape, one of the dataframes will have to be negative values, while the other can remain positive. In this case, we can make the dataframe for males be negative, so appearing on the left of the chart. Also, isolate only results from 2019 here.
dataM['Pop']=-dataM['Pop']
dataPrepped=bind_rows(dataF,dataM)
filter(dataPrepped,Time==2020)
## # A tibble: 100,928 x 7
## PA SZ AG Sex TOD Pop Time
## <chr> <chr> <chr> <chr> <chr> <dbl> <dbl>
## 1 Ang Mo K~ Ang Mo Kio Town~ 0_to~ Femal~ HDB 1- and 2-Room Flats 0 2020
## 2 Ang Mo K~ Ang Mo Kio Town~ 0_to~ Femal~ HDB 3-Room Flats 10 2020
## 3 Ang Mo K~ Ang Mo Kio Town~ 0_to~ Femal~ HDB 4-Room Flats 10 2020
## 4 Ang Mo K~ Ang Mo Kio Town~ 0_to~ Femal~ HDB 5-Room and Executive~ 20 2020
## 5 Ang Mo K~ Ang Mo Kio Town~ 0_to~ Femal~ HUDC Flats (excluding th~ 0 2020
## 6 Ang Mo K~ Ang Mo Kio Town~ 0_to~ Femal~ Landed Properties 0 2020
## 7 Ang Mo K~ Ang Mo Kio Town~ 0_to~ Femal~ Condominiums and Other A~ 40 2020
## 8 Ang Mo K~ Ang Mo Kio Town~ 0_to~ Femal~ Others 0 2020
## 9 Ang Mo K~ Ang Mo Kio Town~ 5_to~ Femal~ HDB 1- and 2-Room Flats 0 2020
## 10 Ang Mo K~ Ang Mo Kio Town~ 5_to~ Femal~ HDB 3-Room Flats 10 2020
## # ... with 100,918 more rows
#head(dataF)
#head(dataM)
Creating the population pyramid
ggplot(data=dataPrepped,aes(x = AG, y = Pop, fill = Sex)) +
geom_bar(stat = "identity", width = .6) +
scale_y_continuous() + coord_flip() +
labs(title="Singapore's Population pyramid in 2019",
x = "Age", y = "Population")+
theme(plot.title = element_text(hjust = .5),
axis.ticks = element_blank()) +
scale_fill_brewer(palette = "Set1")
From the above preliminary visualisation, we can see the y-axis will have to be manually put in order.
dataPrepped$AG<-factor(dataPrepped$AG,levels=c('0_to_4','5_to_9',"10_to_14","15_to_19","20_to_24","25_to_29",
"30_to_34","35_to_39","40_to_44","45_to_49","50_to_54","55_to_59",
"60_to_64","65_to_69","70_to_74","75_to_79","80_to_84","85_to_89",
"90_and_over"))
ggplot(data=dataPrepped,aes(x = AG, y = Pop, fill = Sex)) +
geom_bar(stat = "identity", width = .6) +
scale_y_continuous() + coord_flip() +
labs(title="Singapore's population pyramid in 2019",
x = "Age", y = "Population")+
theme(plot.title = element_text(hjust = .5),
axis.ticks = element_blank()) +
scale_fill_brewer(palette = "Set1")
Next step will be building the UI to view the visualisation. Apart from a panel for the population pyramid, we will need options in the form of a dropdown list to be able to select which planning area we want to view. The dropdown list will contain all unique planning area values.
ui <- fluidPage(
titlePanel("Singapore's population pyramid (2019)"),
sidebarLayout(
position = "right",
sidebarPanel(
selectInput(inputId = 'PA',
label = 'Planning Area:',
choices = unique(dataPrepped$PA))
),
mainPanel(
h3("Singapore Population pyramid",align='center'),
plotOutput('barchart'),
tableOutput("values"),
width=9
)
)
)
Next, to display the UI on server side. We use input$PA to be able to select the planning area variable we want to view the chart for. The pyramid barchart is then rendered into the panel.
server <- function(input,output,session){
observe({
x <- input$PA #Selection of PA
# To remove selection if null
if (is.null(x))
x <- character(0)
selection = select(filter(dataPrepped,PA==input$PA))
})
output$barchart <- renderPlot({
filter(dataPrepped,PA==input$PA)
ggplot(data=dataPrepped,aes(x = AG, y = Pop, fill = Sex)) +
geom_bar(stat = "identity") + scale_y_continuous() +
coord_flip() + labs(x='Age Group',y="Population", caption = "Singapore population pyramid, 2019")+
theme(axis.ticks = element_blank(),
axis.title.x=element_text(size=14,face="bold"), axis.title.y=element_text(size=14,face='bold'),
axis.text.x = element_text(size = 14), axis.text.y = element_text(size = 14),
legend.text = element_text(size = 14)) +
scale_fill_discrete(name="Gender",breaks=c("Males", "Females"), labels=c("Males", "Females")) +
scale_fill_brewer(palette = "Set1")
})
}
shinyApp(ui = ui, server = server)