Writing about visualization, demographics, dashboards, and spatial data science.

Interested in learning more? Hire me for a workshop or to consult on your next project. See the Services page for more details.

Life expectancy trends in the former USSR

· by Kyle Walker · Read in about 7 min · (1352 Words)
R rCharts Shiny

When covering Russia and the former republics of the USSR in World Regional Geography, a key part of my material addresses the issues that some of these countries have had in their transitions from centralized to market economies. Some of these countries experienced dramatic demographic shifts after the dissolution of the USSR, including a noticeable decline in life expectancy.

I’d been using some static Excel charts to illustrate life expectancy declines in Russia, Belarus, and Ukraine in previous courses. However, I felt that an interactive solution would be preferable so that my students and I could explore the data in class over the course of our discussion. I opted for Highcharts, through R and rCharts, for the interactivity. I then turned to Shiny from RStudio to put everything together.

Shiny is a framework that allows R users to turn analyses and visualizations into interactive applications. Shiny can be run locally on your computer, or deployed to the web via the ShinyApps.io hosting service, which is currently free. The beauty of Shiny is that it allows you to explore your data interactively with a friendly web-based user interface without writing any JavaScript, and it lets R users create and deploy apps to be shared with non-R users who may nonetheless be interested in exploring a dataset or visualization. You can see RStudio’s gallery of examples here.

To get started, I acquired data from The Human Mortality Database, (HMD) a project of UC Berkeley and the Max Planck Institute. The HMD prefers that users not re-distribute the data, so if you’d like to reproduce this chart, you’ll need to download the data yourself. However, the service is free (with registration) and relatively simple to use. The HMD provides mortality data for 37 countries, including Russia, Belarus, and Ukraine. From the HMD, I downloaded the 1-year life expectancy at birth tables for these countries, and saved them to my working directory as delimited text files, naming them accordingly. Once I did this, I used the code below to process the data into a suitable format for visualization.


library(tidyr)
library(dplyr)

russia <- read.table('russia.txt', skip = 3)

names(russia) <- c("Year", "Female", "Male", "Total")

russia$country <- "Russia"

ukraine <- read.table('ukraine.txt', skip = 3)

names(ukraine) <- c("Year", "Female", "Male", "Total")

ukraine$country <- "Ukraine"

belarus <- read.table('belarus.txt', skip = 3)

names(belarus) <- c("Year", "Female", "Male", "Total")

belarus$country <- "Belarus"

dat <- rbind(russia, ukraine, belarus)

dlong <- dat %>%
  select(-Total) %>%
  gather(Gender, lex, Female:Male)

write.csv(dlong, 'data.csv')

In a nutshell, the above code reads in each of the three text files, identifies the country the data correspond to, then combines them. It then uses functions from the dplyr and tidyr packages to convert the data to “tidy” (long) format, which is what I want for visualization. I then saved the data as a CSV and moved it to a new folder where I would create my Shiny app.

A Shiny app requires two files to run: server.R, which specifies the data analysis/visualization to show, and ui.R, in which you prepare the user interface. An optional third file (which I haven’t used here), global.R, can be used to read in data or do any background data preparation that you want to make available to both the server and UI scripts. I largely adapted my server and UI code from RStudio’s Shiny tutorials and Ramnath Vaidyanathan’s tutorial on using rCharts with Shiny, with some help from StackOverflow as well.

I prepared the UI first with the code below.


# ui.R

library(rCharts)

dat <- read.csv('data.csv')

# Define UI 
shinyUI(fluidPage(
  
  # Sidebar 
  sidebarLayout(
    sidebarPanel(
      selectInput(inputId = "country", 
                  label = "Select a country:", 
                  choices = c("Russia", "Belarus", "Ukraine"), 
                  selected = "Russia"), 
      sliderInput("range",
                  label = "Years to display:",
                  min = 1959,
                  max = 2010,
                  value = c(1959, 2010), 
                  format = "0000"), 
      helpText("Data reflect the life expectancy ", 
                "at birth from 1959 to 2010 ", 
               "for men and women in Russia, ", 
                "Belarus, and Ukraine.  Data are ", 
               "obtained from the Human Mortality ", 
                "Database, a project of ", 
                " the University of California, ", 
                "Berkeley (USA), and Max Planck ", 
                "Institute for Demographic Research ", 
                "(Germany). Data are available ", 
                "at www.mortality.org or www.humanmortality.de ", 
               "(downloaded on 14 Oct 2014).")
    ),
    
    # Show the plot 
    mainPanel(
      showOutput("lexplot", "highcharts")
    )
  )
))

In the ui.R script, I define the parameters of the Shiny user interface. I’ll have a drop-down menu to select the country of choice (Russia, Belarus, or Ukraine), as well as a time slider that allows the user to specify the years to show in the chart. I then use the showOutput function from rCharts in the mainPanel call to tell Shiny to show my chart in the main area.

Next, I set up the server.


# server.R

library(rCharts)

dat <- read.csv('data.csv')

options(RCHART_WIDTH = 500)

shinyServer(function(input, output) {
  output$lexplot <- renderChart2({
    selected <- input$country
    country <- subset(dat, country == selected & Year %in% seq(input$range[1], input$range[2], 1))
    h1 <- hPlot(
      x = "Year", 
      y = "lex", 
      group = "Gender", 
      data = country, 
      type = "line")
    
    h1$colors(c("red", "blue"))
    h1$yAxis(title = list(enabled = TRUE, text = 'Life expectancy at birth'))
    return(h1)
  })
})

The key here to get this to work is to make sure that your server.R and ui.R scripts communicate correctly. My UI takes an input that is dependent upon the country and years selected by the user, so I create a subsetted data frame, country, within the renderChart2 function that will respond to that. I then specify the parameters of the Highchart plot, and tell my renderChart2 function to return that plot and assign it to the lexplot property of the output, which is what my user interface script will expect.

RStudio will know that you are creating a Shiny app (given the names of your scripts), so you can simply click the Run App button to run your app locally, and then deploy it to ShinyApps if you’d like. Now, let’s take a look at the result. Click the image below to access the application (I’m trying to cut down on my usage for my ShinyApps.io free account). Use the drop-down menu to select a country, and the time slider to specify a range of years to display.



I now have an application that allows me to seamlessly switch between countries, change years, and explore the data thanks to Highcharts’ built-in interactivity. The charts reveal key trends in life expectancy both pre- and post- USSR. In Russia, for example, we see that life expectancy declines through the mid-20th century, then peaks in the 1980s, which is attributed to Mikhail Gorbachev’s anti-alcohol campaign. Life expectancy then falls dramatically around the time that the USSR dissolved. For example, male life expectancy in 1994 in Russia was a little over 57, around 7.5 years less than its peak in 1987. Studies have attributed this to a variety of factors, including alcohol abuse, poor nutrition and health behaviors, and problems with the health care system. However, life expectancy improves in the late 2000s, in part due to declines in cardiovascular disease and homicides.

In class, I first presented the chart (which displays very nicely in a Slidify presentation) and explored the data with my students. I then showed my students the first segment from the documentary Death of a Nation: Russia by Marcel Theroux which explores some of the underlying issues behind these demographic changes in more depth. We then used the video to collectively think about some reasons for the decline of life expectancy in Russia after the fall of the USSR. The video paired very nicely with the interactive Shiny app; the charts provided key visual demographic context, and the video then put faces to the data.

The app is fully reproducible (just make sure you download the data from the Human Mortality Database first) and you can find the code in its GitHub repository. Feel free to use the app as you’d like, or modify the code as you wish to create your own apps!

Thanks to:

  • The creators of the Human Mortality Database for making their data freely available
  • The RStudio team for Shiny and all its associated training materials
  • The developers of rCharts and Highcharts